/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0
});
/**** 
* Classes
****/ 
var Boss = Container.expand(function () {
	var self = Container.call(this);
	var bossGraphics = self.attachAsset('boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.health = 30;
	self.maxHealth = 30;
	self.phase = 1;
	self.attackCooldown = 0;
	self.moveDir = 1;
	self.speed = 3;
	self.pointValue = 2000;
	self.takeDamage = function (damage) {
		self.health -= damage;
		// Update health bar
		updateBossHealthBar();
		if (self.health <= 0) {
			// Add score
			LK.setScore(LK.getScore() + self.pointValue);
			// Create multiple explosions
			for (var i = 0; i < 5; i++) {
				var offsetX = (Math.random() - 0.5) * 200;
				var offsetY = (Math.random() - 0.5) * 150;
				createExplosion(self.x + offsetX, self.y + offsetY);
				// Stagger the explosion sounds
				LK.setTimeout(function () {
					LK.getSound('explosion').play();
				}, i * 300);
			}
			// Level complete
			LK.showYouWin();
			return true;
		}
		// Change phase at 50% health
		if (self.health < self.maxHealth / 2 && self.phase === 1) {
			self.phase = 2;
			self.speed = 5;
			LK.effects.flashObject(self, 0xffff00, 500);
		}
		// Flash red when hit
		LK.effects.flashObject(self, 0xff0000, 200);
		return false;
	};
	self.update = function () {
		// Side to side movement
		self.x += self.speed * self.moveDir;
		if (self.x > 1800 || self.x < 248) {
			self.moveDir *= -1;
		}
		// Attack patterns
		self.attackCooldown--;
		if (self.attackCooldown <= 0) {
			if (self.phase === 1) {
				// Phase 1: Single line of bullets
				for (var i = -2; i <= 2; i++) {
					fireBullet(self.x + i * 50, self.y + 50, "enemy");
				}
				self.attackCooldown = 60;
			} else {
				// Phase 2: More complex patterns
				if (Math.random() < 0.5) {
					// Spiral pattern
					for (var i = 0; i < 8; i++) {
						var angle = i / 8 * Math.PI * 2;
						var bulletX = self.x + Math.cos(angle) * 100;
						var bulletY = self.y + Math.sin(angle) * 100;
						fireBullet(bulletX, bulletY, "enemy");
					}
				} else {
					// Cross pattern
					for (var i = -2; i <= 2; i++) {
						fireBullet(self.x + i * 60, self.y + 50, "enemy");
						fireBullet(self.x, self.y + 50 + i * 60, "enemy");
					}
				}
				self.attackCooldown = 45;
			}
			LK.getSound('enemyShoot').play();
		}
	};
	return self;
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.health = 2;
	self.speed = 2;
	self.fireChance = 0.005; // Chance to fire each frame
	self.movementPattern = "descent"; // Default pattern
	self.pointValue = 100;
	self.moveDir = 1;
	self.initY = 0;
	self.amplitude = 100;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			// Add score
			LK.setScore(LK.getScore() + self.pointValue);
			// Create explosion
			createExplosion(self.x, self.y);
			LK.getSound('explosion').play();
			// Chance to drop powerup
			if (Math.random() < 0.2) {
				createPowerUp(self.x, self.y);
			}
			// Remove enemy
			return true;
		}
		// Flash red when hit
		LK.effects.flashObject(self, 0xff0000, 200);
		return false;
	};
	self.update = function () {
		// Different movement patterns
		if (self.movementPattern === "descent") {
			self.y += self.speed;
		} else if (self.movementPattern === "zigzag") {
			self.x += self.speed * self.moveDir;
			self.y += self.speed * 0.5;
			// Change direction at edges
			if (self.x > 1900 || self.x < 148) {
				self.moveDir *= -1;
			}
		} else if (self.movementPattern === "sine") {
			self.y += self.speed;
			self.x = self.initX + Math.sin((self.y - self.initY) * 0.02) * self.amplitude;
		}
		// Random chance to fire
		if (Math.random() < self.fireChance) {
			fireBullet(self.x, self.y, "enemy");
		}
	};
	return self;
});
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var Explosion = Container.expand(function () {
	var self = Container.call(this);
	var explosionGraphics = self.attachAsset('explosion', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.9
	});
	self.lifespan = 20;
	self.update = function () {
		self.lifespan--;
		// Grow and fade out
		explosionGraphics.alpha = self.lifespan / 20;
		explosionGraphics.scaleX = (20 - self.lifespan) / 10;
		explosionGraphics.scaleY = (20 - self.lifespan) / 10;
		if (self.lifespan <= 0) {
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var shipGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.fireRate = 10;
	self.lastFired = 0;
	self.health = 3;
	self.shield = false;
	self.shieldGraphics = null;
	self.invulnerable = false;
	self.activateShield = function () {
		if (!self.shield) {
			self.shield = true;
			self.shieldGraphics = self.attachAsset('shield', {
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.5
			});
			self.shieldGraphics.blendMode = "screen"; // This line has no effect, but kept for demonstration
			// Shield expires after 10 seconds
			LK.setTimeout(function () {
				if (self.shieldGraphics) {
					self.shield = false;
					self.removeChild(self.shieldGraphics);
					self.shieldGraphics = null;
				}
			}, 10000);
		}
	};
	self.takeDamage = function () {
		if (!self.invulnerable) {
			if (self.shield) {
				self.shield = false;
				if (self.shieldGraphics) {
					self.removeChild(self.shieldGraphics);
					self.shieldGraphics = null;
				}
			} else {
				self.health--;
				// Make player briefly invulnerable after taking damage
				self.invulnerable = true;
				// Flash effect
				var flashCount = 0;
				var flashInterval = LK.setInterval(function () {
					shipGraphics.alpha = shipGraphics.alpha === 1 ? 0.3 : 1;
					flashCount++;
					if (flashCount >= 10) {
						LK.clearInterval(flashInterval);
						shipGraphics.alpha = 1;
						self.invulnerable = false;
					}
				}, 150);
				if (self.health <= 0) {
					createExplosion(self.x, self.y);
					LK.getSound('explosion').play();
					LK.showGameOver();
				}
			}
		}
	};
	return self;
});
var PlayerBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('playerBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -15;
	self.damage = 1;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = "shield"; // Default
	self.speed = 3;
	// Visual effect - pulsate
	tween(powerUpGraphics, {
		alpha: 0.6
	}, {
		duration: 500,
		easing: tween.sinOut,
		onFinish: function onFinish() {
			tween(powerUpGraphics, {
				alpha: 1
			}, {
				duration: 500,
				easing: tween.sinIn,
				onFinish: function onFinish() {
					// Continuous pulsating
					if (self.parent) {
						tween(powerUpGraphics, {
							alpha: 0.6
						}, {
							duration: 500,
							easing: tween.sinOut,
							onFinish: arguments.callee
						});
					}
				}
			});
		}
	});
	self.update = function () {
		self.y += self.speed;
	};
	self.collect = function () {
		LK.getSound('powerUp').play();
		if (self.type === "shield") {
			player.activateShield();
		} else if (self.type === "fireRate") {
			player.fireRate = 5;
			// Revert to normal fire rate after 10 seconds
			LK.setTimeout(function () {
				player.fireRate = 10;
			}, 10000);
		} else if (self.type === "health") {
			player.health = Math.min(player.health + 1, 5);
			updateLives();
		}
		return true;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000022
});
/**** 
* Game Code
****/ 
// Add background image to the game
var background = LK.getAsset('Background', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2,
	scaleX: 2048 / 100,
	// Scale to fit the screen width
	scaleY: 2732 / 100 // Scale to fit the screen height
});
game.addChild(background);
var player;
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerUps = [];
var explosions = [];
var gameStarted = false;
var boss = null;
var waveNumber = 1;
var enemiesPerWave = 10;
var waveDelay = 0;
var dragNode = null;
var bossHealthBar;
var bossHealthBarBg;
var lives = [];
// Setup score display
var scoreTxt = new Text2('Score: 0', {
	size: 50,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -scoreTxt.width - 20;
scoreTxt.y = 20;
// High score display
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
	size: 40,
	fill: 0xBBBBFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -highScoreTxt.width - 20;
highScoreTxt.y = 80;
// Wave indicator
var waveTxt = new Text2('Wave: 1', {
	size: 50,
	fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
LK.gui.top.addChild(waveTxt);
waveTxt.y = 20;
// Create player
function createPlayer() {
	player = new Player();
	player.x = 2048 / 2;
	player.y = 2732 - 200;
	game.addChild(player);
	// Setup life display
	updateLives();
}
// Life display
function updateLives() {
	// Clear existing lives
	for (var i = 0; i < lives.length; i++) {
		LK.gui.topLeft.removeChild(lives[i]);
	}
	lives = [];
	// Create life indicators
	for (var i = 0; i < player.health; i++) {
		var life = LK.getAsset('player', {
			scaleX: 0.4,
			scaleY: 0.4,
			anchorX: 0,
			anchorY: 0,
			x: 120 + i * 60,
			y: 20
		});
		lives.push(life);
		LK.gui.topLeft.addChild(life);
	}
}
// Create boss health bar
function createBossHealthBar() {
	bossHealthBarBg = LK.getAsset('playerBullet', {
		width: 1000,
		height: 30,
		anchorX: 0.5,
		anchorY: 0,
		tint: 0x333333
	});
	bossHealthBarBg.x = 0;
	bossHealthBarBg.y = 100;
	bossHealthBar = LK.getAsset('playerBullet', {
		width: 1000,
		height: 30,
		anchorX: 0,
		anchorY: 0,
		tint: 0xff0000
	});
	bossHealthBar.x = -500;
	bossHealthBar.y = 100;
	LK.gui.top.addChild(bossHealthBarBg);
	LK.gui.top.addChild(bossHealthBar);
}
function updateBossHealthBar() {
	if (boss && bossHealthBar) {
		var percentage = boss.health / boss.maxHealth;
		bossHealthBar.width = 1000 * percentage;
	}
}
function removeBossHealthBar() {
	if (bossHealthBarBg) {
		LK.gui.top.removeChild(bossHealthBarBg);
		bossHealthBarBg = null;
	}
	if (bossHealthBar) {
		LK.gui.top.removeChild(bossHealthBar);
		bossHealthBar = null;
	}
}
// Fire a bullet
function fireBullet(x, y, type) {
	var bullet;
	if (type === "player") {
		bullet = new PlayerBullet();
		playerBullets.push(bullet);
		LK.getSound('playerShoot').play();
	} else {
		bullet = new EnemyBullet();
		enemyBullets.push(bullet);
	}
	bullet.x = x;
	bullet.y = y;
	game.addChild(bullet);
}
// Create an explosion effect
function createExplosion(x, y) {
	var explosion = new Explosion();
	explosion.x = x;
	explosion.y = y;
	game.addChild(explosion);
	explosions.push(explosion);
}
// Create a power-up
function createPowerUp(x, y) {
	var powerUp = new PowerUp();
	powerUp.x = x;
	powerUp.y = y;
	// Randomly select power-up type
	var types = ["shield", "fireRate", "health"];
	var typeIndex = Math.floor(Math.random() * types.length);
	powerUp.type = types[typeIndex];
	// Set color based on type
	var powerUpGraphics = powerUp.getChildAt(0);
	if (powerUp.type === "shield") {
		powerUpGraphics.tint = 0x3498db; // Blue
	} else if (powerUp.type === "fireRate") {
		powerUpGraphics.tint = 0xf39c12; // Orange
	} else if (powerUp.type === "health") {
		powerUpGraphics.tint = 0xe74c3c; // Red
	}
	game.addChild(powerUp);
	powerUps.push(powerUp);
}
// Spawn an enemy
function spawnEnemy(x, y, pattern) {
	var enemy = new Enemy();
	enemy.x = x;
	enemy.y = y;
	enemy.movementPattern = pattern;
	if (pattern === "sine") {
		enemy.initX = x;
		enemy.initY = y;
	}
	// Adjust difficulty based on wave
	enemy.health = 1 + Math.floor(waveNumber / 3);
	enemy.speed = 1 + waveNumber * 0.2;
	game.addChild(enemy);
	enemies.push(enemy);
}
// Spawn a boss
function spawnBoss() {
	boss = new Boss();
	boss.x = 2048 / 2;
	boss.y = 300;
	// Adjust boss difficulty based on wave
	boss.health = 20 + waveNumber * 5;
	boss.maxHealth = boss.health;
	game.addChild(boss);
	// Create boss health bar
	createBossHealthBar();
	// Play boss music
	LK.getSound('bossFight').play();
}
// Spawn a wave of enemies
function spawnWave() {
	// Every 3 waves, spawn a boss
	if (waveNumber % 3 === 0) {
		spawnBoss();
		return;
	}
	// Regular enemy wave
	var numEnemies = enemiesPerWave + waveNumber * 2;
	var patterns = ["descent", "zigzag", "sine"];
	for (var i = 0; i < numEnemies; i++) {
		var x = 200 + Math.random() * (2048 - 400);
		var y = -100 - i * 80;
		var pattern = patterns[Math.floor(Math.random() * patterns.length)];
		spawnEnemy(x, y, pattern);
	}
}
// Start a new wave
function startNewWave() {
	waveNumber++;
	waveTxt.setText('Wave: ' + waveNumber);
	spawnWave();
}
// Initialize game
function initGame() {
	// Initialize start message
	startText = new Text2('Tap to Start', {
		size: 100,
		fill: 0xFFFFFF
	});
	startText.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(startText);
	playerBullets = [];
	enemyBullets = [];
	enemies = [];
	powerUps = [];
	explosions = [];
	gameStarted = true;
	if (startText && startText.parent) {
		LK.gui.center.removeChild(startText);
	}
	startText = null;
	waveNumber = 0;
	boss = null;
	// Reset score
	LK.setScore(0);
	scoreTxt.setText('Score: 0');
	highScoreTxt.setText('High Score: ' + storage.highScore);
	// Create player
	createPlayer();
	// Start first wave
	startNewWave();
	// Play game music
	LK.playMusic('gameMusic');
}
// Handle movement of player
function handleMove(x, y, obj) {
	if (dragNode) {
		dragNode.x = x;
		// Limit player movement to bottom third of screen
		dragNode.y = Math.max(y, 2732 / 3 * 2);
		// Keep player on screen
		dragNode.x = Math.max(dragNode.x, 100);
		dragNode.x = Math.min(dragNode.x, 2048 - 100);
		dragNode.y = Math.min(dragNode.y, 2732 - 100);
	}
}
// Event handlers
game.move = handleMove;
game.down = function (x, y, obj) {
	if (!gameStarted) {
		initGame();
		if (startText && startText.parent) {
			LK.gui.center.removeChild(startText);
		}
		startText = null;
	} else if (player) {
		dragNode = player;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Game update loop
game.update = function () {
	if (!gameStarted) {
		return;
	}
	// Update score display
	scoreTxt.setText('Score: ' + LK.getScore());
	// Player shooting
	if (player && LK.ticks % player.fireRate === 0) {
		fireBullet(player.x, player.y - 50, "player");
	}
	// Update player bullets
	for (var i = playerBullets.length - 1; i >= 0; i--) {
		var bullet = playerBullets[i];
		// Remove bullets that go off screen
		if (bullet.y < -50) {
			bullet.destroy();
			playerBullets.splice(i, 1);
			continue;
		}
		// Check for collision with enemies
		var hitEnemy = false;
		for (var j = enemies.length - 1; j >= 0; j--) {
			var enemy = enemies[j];
			if (bullet.intersects(enemy)) {
				// Apply damage to enemy
				if (enemy.takeDamage(bullet.damage)) {
					enemy.destroy();
					enemies.splice(j, 1);
				}
				// Remove bullet
				bullet.destroy();
				playerBullets.splice(i, 1);
				hitEnemy = true;
				break;
			}
		}
		// Check for collision with boss
		if (!hitEnemy && boss && bullet.intersects(boss)) {
			boss.takeDamage(bullet.damage);
			// Remove bullet
			bullet.destroy();
			playerBullets.splice(i, 1);
			// Check if boss is defeated
			if (boss.health <= 0) {
				boss.destroy();
				boss = null;
				removeBossHealthBar();
				waveDelay = 180; // Delay before next wave
			}
		}
	}
	// Update enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		// Remove bullets that go off screen
		if (bullet.y > 2732 + 50) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
			continue;
		}
		// Check for collision with player
		if (player && bullet.intersects(player)) {
			player.takeDamage();
			updateLives();
			// Remove bullet
			bullet.destroy();
			enemyBullets.splice(i, 1);
		}
	}
	// Update enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		// Remove enemies that go off screen
		if (enemy.y > 2732 + 100) {
			enemy.destroy();
			enemies.splice(i, 1);
			continue;
		}
		// Check for collision with player
		if (player && enemy.intersects(player)) {
			player.takeDamage();
			updateLives();
			// Remove enemy
			createExplosion(enemy.x, enemy.y);
			LK.getSound('explosion').play();
			enemy.destroy();
			enemies.splice(i, 1);
		}
	}
	// Update power-ups
	for (var i = powerUps.length - 1; i >= 0; i--) {
		var powerUp = powerUps[i];
		// Remove power-ups that go off screen
		if (powerUp.y > 2732 + 50) {
			powerUp.destroy();
			powerUps.splice(i, 1);
			continue;
		}
		// Check for collision with player
		if (player && powerUp.intersects(player)) {
			if (powerUp.collect()) {
				powerUp.destroy();
				powerUps.splice(i, 1);
			}
		}
	}
	// Update explosions
	for (var i = explosions.length - 1; i >= 0; i--) {
		var explosion = explosions[i];
		if (explosion.update()) {
			explosions.splice(i, 1);
		}
	}
	// Check if all enemies are defeated
	if (enemies.length === 0 && !boss) {
		if (waveDelay > 0) {
			waveDelay--;
		} else {
			startNewWave();
		}
	}
	// Update high score
	if (LK.getScore() > storage.highScore) {
		storage.highScore = LK.getScore();
		highScoreTxt.setText('High Score: ' + storage.highScore);
	}
};
// Initialize game with a start message
var startText = null;
var startText = new Text2('Tap to Start', {
	size: 100,
	fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
// Remove start text when game starts
LK.on('tick', function () {
	if (gameStarted && startText && startText.parent) {
		LK.gui.center.removeChild(startText);
	}
}); /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
	highScore: 0
});
/**** 
* Classes
****/ 
var Boss = Container.expand(function () {
	var self = Container.call(this);
	var bossGraphics = self.attachAsset('boss', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.health = 30;
	self.maxHealth = 30;
	self.phase = 1;
	self.attackCooldown = 0;
	self.moveDir = 1;
	self.speed = 3;
	self.pointValue = 2000;
	self.takeDamage = function (damage) {
		self.health -= damage;
		// Update health bar
		updateBossHealthBar();
		if (self.health <= 0) {
			// Add score
			LK.setScore(LK.getScore() + self.pointValue);
			// Create multiple explosions
			for (var i = 0; i < 5; i++) {
				var offsetX = (Math.random() - 0.5) * 200;
				var offsetY = (Math.random() - 0.5) * 150;
				createExplosion(self.x + offsetX, self.y + offsetY);
				// Stagger the explosion sounds
				LK.setTimeout(function () {
					LK.getSound('explosion').play();
				}, i * 300);
			}
			// Level complete
			LK.showYouWin();
			return true;
		}
		// Change phase at 50% health
		if (self.health < self.maxHealth / 2 && self.phase === 1) {
			self.phase = 2;
			self.speed = 5;
			LK.effects.flashObject(self, 0xffff00, 500);
		}
		// Flash red when hit
		LK.effects.flashObject(self, 0xff0000, 200);
		return false;
	};
	self.update = function () {
		// Side to side movement
		self.x += self.speed * self.moveDir;
		if (self.x > 1800 || self.x < 248) {
			self.moveDir *= -1;
		}
		// Attack patterns
		self.attackCooldown--;
		if (self.attackCooldown <= 0) {
			if (self.phase === 1) {
				// Phase 1: Single line of bullets
				for (var i = -2; i <= 2; i++) {
					fireBullet(self.x + i * 50, self.y + 50, "enemy");
				}
				self.attackCooldown = 60;
			} else {
				// Phase 2: More complex patterns
				if (Math.random() < 0.5) {
					// Spiral pattern
					for (var i = 0; i < 8; i++) {
						var angle = i / 8 * Math.PI * 2;
						var bulletX = self.x + Math.cos(angle) * 100;
						var bulletY = self.y + Math.sin(angle) * 100;
						fireBullet(bulletX, bulletY, "enemy");
					}
				} else {
					// Cross pattern
					for (var i = -2; i <= 2; i++) {
						fireBullet(self.x + i * 60, self.y + 50, "enemy");
						fireBullet(self.x, self.y + 50 + i * 60, "enemy");
					}
				}
				self.attackCooldown = 45;
			}
			LK.getSound('enemyShoot').play();
		}
	};
	return self;
});
var Enemy = Container.expand(function () {
	var self = Container.call(this);
	var enemyGraphics = self.attachAsset('enemy', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.health = 2;
	self.speed = 2;
	self.fireChance = 0.005; // Chance to fire each frame
	self.movementPattern = "descent"; // Default pattern
	self.pointValue = 100;
	self.moveDir = 1;
	self.initY = 0;
	self.amplitude = 100;
	self.takeDamage = function (damage) {
		self.health -= damage;
		if (self.health <= 0) {
			// Add score
			LK.setScore(LK.getScore() + self.pointValue);
			// Create explosion
			createExplosion(self.x, self.y);
			LK.getSound('explosion').play();
			// Chance to drop powerup
			if (Math.random() < 0.2) {
				createPowerUp(self.x, self.y);
			}
			// Remove enemy
			return true;
		}
		// Flash red when hit
		LK.effects.flashObject(self, 0xff0000, 200);
		return false;
	};
	self.update = function () {
		// Different movement patterns
		if (self.movementPattern === "descent") {
			self.y += self.speed;
		} else if (self.movementPattern === "zigzag") {
			self.x += self.speed * self.moveDir;
			self.y += self.speed * 0.5;
			// Change direction at edges
			if (self.x > 1900 || self.x < 148) {
				self.moveDir *= -1;
			}
		} else if (self.movementPattern === "sine") {
			self.y += self.speed;
			self.x = self.initX + Math.sin((self.y - self.initY) * 0.02) * self.amplitude;
		}
		// Random chance to fire
		if (Math.random() < self.fireChance) {
			fireBullet(self.x, self.y, "enemy");
		}
	};
	return self;
});
var EnemyBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('enemyBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = 8;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var Explosion = Container.expand(function () {
	var self = Container.call(this);
	var explosionGraphics = self.attachAsset('explosion', {
		anchorX: 0.5,
		anchorY: 0.5,
		alpha: 0.9
	});
	self.lifespan = 20;
	self.update = function () {
		self.lifespan--;
		// Grow and fade out
		explosionGraphics.alpha = self.lifespan / 20;
		explosionGraphics.scaleX = (20 - self.lifespan) / 10;
		explosionGraphics.scaleY = (20 - self.lifespan) / 10;
		if (self.lifespan <= 0) {
			self.destroy();
			return true;
		}
		return false;
	};
	return self;
});
var Player = Container.expand(function () {
	var self = Container.call(this);
	var shipGraphics = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.fireRate = 10;
	self.lastFired = 0;
	self.health = 3;
	self.shield = false;
	self.shieldGraphics = null;
	self.invulnerable = false;
	self.activateShield = function () {
		if (!self.shield) {
			self.shield = true;
			self.shieldGraphics = self.attachAsset('shield', {
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.5
			});
			self.shieldGraphics.blendMode = "screen"; // This line has no effect, but kept for demonstration
			// Shield expires after 10 seconds
			LK.setTimeout(function () {
				if (self.shieldGraphics) {
					self.shield = false;
					self.removeChild(self.shieldGraphics);
					self.shieldGraphics = null;
				}
			}, 10000);
		}
	};
	self.takeDamage = function () {
		if (!self.invulnerable) {
			if (self.shield) {
				self.shield = false;
				if (self.shieldGraphics) {
					self.removeChild(self.shieldGraphics);
					self.shieldGraphics = null;
				}
			} else {
				self.health--;
				// Make player briefly invulnerable after taking damage
				self.invulnerable = true;
				// Flash effect
				var flashCount = 0;
				var flashInterval = LK.setInterval(function () {
					shipGraphics.alpha = shipGraphics.alpha === 1 ? 0.3 : 1;
					flashCount++;
					if (flashCount >= 10) {
						LK.clearInterval(flashInterval);
						shipGraphics.alpha = 1;
						self.invulnerable = false;
					}
				}, 150);
				if (self.health <= 0) {
					createExplosion(self.x, self.y);
					LK.getSound('explosion').play();
					LK.showGameOver();
				}
			}
		}
	};
	return self;
});
var PlayerBullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletGraphics = self.attachAsset('playerBullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -15;
	self.damage = 1;
	self.update = function () {
		self.y += self.speed;
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	var powerUpGraphics = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.type = "shield"; // Default
	self.speed = 3;
	// Visual effect - pulsate
	tween(powerUpGraphics, {
		alpha: 0.6
	}, {
		duration: 500,
		easing: tween.sinOut,
		onFinish: function onFinish() {
			tween(powerUpGraphics, {
				alpha: 1
			}, {
				duration: 500,
				easing: tween.sinIn,
				onFinish: function onFinish() {
					// Continuous pulsating
					if (self.parent) {
						tween(powerUpGraphics, {
							alpha: 0.6
						}, {
							duration: 500,
							easing: tween.sinOut,
							onFinish: arguments.callee
						});
					}
				}
			});
		}
	});
	self.update = function () {
		self.y += self.speed;
	};
	self.collect = function () {
		LK.getSound('powerUp').play();
		if (self.type === "shield") {
			player.activateShield();
		} else if (self.type === "fireRate") {
			player.fireRate = 5;
			// Revert to normal fire rate after 10 seconds
			LK.setTimeout(function () {
				player.fireRate = 10;
			}, 10000);
		} else if (self.type === "health") {
			player.health = Math.min(player.health + 1, 5);
			updateLives();
		}
		return true;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000022
});
/**** 
* Game Code
****/ 
// Add background image to the game
var background = LK.getAsset('Background', {
	anchorX: 0.5,
	anchorY: 0.5,
	x: 2048 / 2,
	y: 2732 / 2,
	scaleX: 2048 / 100,
	// Scale to fit the screen width
	scaleY: 2732 / 100 // Scale to fit the screen height
});
game.addChild(background);
var player;
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerUps = [];
var explosions = [];
var gameStarted = false;
var boss = null;
var waveNumber = 1;
var enemiesPerWave = 10;
var waveDelay = 0;
var dragNode = null;
var bossHealthBar;
var bossHealthBarBg;
var lives = [];
// Setup score display
var scoreTxt = new Text2('Score: 0', {
	size: 50,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -scoreTxt.width - 20;
scoreTxt.y = 20;
// High score display
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
	size: 40,
	fill: 0xBBBBFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -highScoreTxt.width - 20;
highScoreTxt.y = 80;
// Wave indicator
var waveTxt = new Text2('Wave: 1', {
	size: 50,
	fill: 0xFFFFFF
});
waveTxt.anchor.set(0, 0);
LK.gui.top.addChild(waveTxt);
waveTxt.y = 20;
// Create player
function createPlayer() {
	player = new Player();
	player.x = 2048 / 2;
	player.y = 2732 - 200;
	game.addChild(player);
	// Setup life display
	updateLives();
}
// Life display
function updateLives() {
	// Clear existing lives
	for (var i = 0; i < lives.length; i++) {
		LK.gui.topLeft.removeChild(lives[i]);
	}
	lives = [];
	// Create life indicators
	for (var i = 0; i < player.health; i++) {
		var life = LK.getAsset('player', {
			scaleX: 0.4,
			scaleY: 0.4,
			anchorX: 0,
			anchorY: 0,
			x: 120 + i * 60,
			y: 20
		});
		lives.push(life);
		LK.gui.topLeft.addChild(life);
	}
}
// Create boss health bar
function createBossHealthBar() {
	bossHealthBarBg = LK.getAsset('playerBullet', {
		width: 1000,
		height: 30,
		anchorX: 0.5,
		anchorY: 0,
		tint: 0x333333
	});
	bossHealthBarBg.x = 0;
	bossHealthBarBg.y = 100;
	bossHealthBar = LK.getAsset('playerBullet', {
		width: 1000,
		height: 30,
		anchorX: 0,
		anchorY: 0,
		tint: 0xff0000
	});
	bossHealthBar.x = -500;
	bossHealthBar.y = 100;
	LK.gui.top.addChild(bossHealthBarBg);
	LK.gui.top.addChild(bossHealthBar);
}
function updateBossHealthBar() {
	if (boss && bossHealthBar) {
		var percentage = boss.health / boss.maxHealth;
		bossHealthBar.width = 1000 * percentage;
	}
}
function removeBossHealthBar() {
	if (bossHealthBarBg) {
		LK.gui.top.removeChild(bossHealthBarBg);
		bossHealthBarBg = null;
	}
	if (bossHealthBar) {
		LK.gui.top.removeChild(bossHealthBar);
		bossHealthBar = null;
	}
}
// Fire a bullet
function fireBullet(x, y, type) {
	var bullet;
	if (type === "player") {
		bullet = new PlayerBullet();
		playerBullets.push(bullet);
		LK.getSound('playerShoot').play();
	} else {
		bullet = new EnemyBullet();
		enemyBullets.push(bullet);
	}
	bullet.x = x;
	bullet.y = y;
	game.addChild(bullet);
}
// Create an explosion effect
function createExplosion(x, y) {
	var explosion = new Explosion();
	explosion.x = x;
	explosion.y = y;
	game.addChild(explosion);
	explosions.push(explosion);
}
// Create a power-up
function createPowerUp(x, y) {
	var powerUp = new PowerUp();
	powerUp.x = x;
	powerUp.y = y;
	// Randomly select power-up type
	var types = ["shield", "fireRate", "health"];
	var typeIndex = Math.floor(Math.random() * types.length);
	powerUp.type = types[typeIndex];
	// Set color based on type
	var powerUpGraphics = powerUp.getChildAt(0);
	if (powerUp.type === "shield") {
		powerUpGraphics.tint = 0x3498db; // Blue
	} else if (powerUp.type === "fireRate") {
		powerUpGraphics.tint = 0xf39c12; // Orange
	} else if (powerUp.type === "health") {
		powerUpGraphics.tint = 0xe74c3c; // Red
	}
	game.addChild(powerUp);
	powerUps.push(powerUp);
}
// Spawn an enemy
function spawnEnemy(x, y, pattern) {
	var enemy = new Enemy();
	enemy.x = x;
	enemy.y = y;
	enemy.movementPattern = pattern;
	if (pattern === "sine") {
		enemy.initX = x;
		enemy.initY = y;
	}
	// Adjust difficulty based on wave
	enemy.health = 1 + Math.floor(waveNumber / 3);
	enemy.speed = 1 + waveNumber * 0.2;
	game.addChild(enemy);
	enemies.push(enemy);
}
// Spawn a boss
function spawnBoss() {
	boss = new Boss();
	boss.x = 2048 / 2;
	boss.y = 300;
	// Adjust boss difficulty based on wave
	boss.health = 20 + waveNumber * 5;
	boss.maxHealth = boss.health;
	game.addChild(boss);
	// Create boss health bar
	createBossHealthBar();
	// Play boss music
	LK.getSound('bossFight').play();
}
// Spawn a wave of enemies
function spawnWave() {
	// Every 3 waves, spawn a boss
	if (waveNumber % 3 === 0) {
		spawnBoss();
		return;
	}
	// Regular enemy wave
	var numEnemies = enemiesPerWave + waveNumber * 2;
	var patterns = ["descent", "zigzag", "sine"];
	for (var i = 0; i < numEnemies; i++) {
		var x = 200 + Math.random() * (2048 - 400);
		var y = -100 - i * 80;
		var pattern = patterns[Math.floor(Math.random() * patterns.length)];
		spawnEnemy(x, y, pattern);
	}
}
// Start a new wave
function startNewWave() {
	waveNumber++;
	waveTxt.setText('Wave: ' + waveNumber);
	spawnWave();
}
// Initialize game
function initGame() {
	// Initialize start message
	startText = new Text2('Tap to Start', {
		size: 100,
		fill: 0xFFFFFF
	});
	startText.anchor.set(0.5, 0.5);
	LK.gui.center.addChild(startText);
	playerBullets = [];
	enemyBullets = [];
	enemies = [];
	powerUps = [];
	explosions = [];
	gameStarted = true;
	if (startText && startText.parent) {
		LK.gui.center.removeChild(startText);
	}
	startText = null;
	waveNumber = 0;
	boss = null;
	// Reset score
	LK.setScore(0);
	scoreTxt.setText('Score: 0');
	highScoreTxt.setText('High Score: ' + storage.highScore);
	// Create player
	createPlayer();
	// Start first wave
	startNewWave();
	// Play game music
	LK.playMusic('gameMusic');
}
// Handle movement of player
function handleMove(x, y, obj) {
	if (dragNode) {
		dragNode.x = x;
		// Limit player movement to bottom third of screen
		dragNode.y = Math.max(y, 2732 / 3 * 2);
		// Keep player on screen
		dragNode.x = Math.max(dragNode.x, 100);
		dragNode.x = Math.min(dragNode.x, 2048 - 100);
		dragNode.y = Math.min(dragNode.y, 2732 - 100);
	}
}
// Event handlers
game.move = handleMove;
game.down = function (x, y, obj) {
	if (!gameStarted) {
		initGame();
		if (startText && startText.parent) {
			LK.gui.center.removeChild(startText);
		}
		startText = null;
	} else if (player) {
		dragNode = player;
		handleMove(x, y, obj);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Game update loop
game.update = function () {
	if (!gameStarted) {
		return;
	}
	// Update score display
	scoreTxt.setText('Score: ' + LK.getScore());
	// Player shooting
	if (player && LK.ticks % player.fireRate === 0) {
		fireBullet(player.x, player.y - 50, "player");
	}
	// Update player bullets
	for (var i = playerBullets.length - 1; i >= 0; i--) {
		var bullet = playerBullets[i];
		// Remove bullets that go off screen
		if (bullet.y < -50) {
			bullet.destroy();
			playerBullets.splice(i, 1);
			continue;
		}
		// Check for collision with enemies
		var hitEnemy = false;
		for (var j = enemies.length - 1; j >= 0; j--) {
			var enemy = enemies[j];
			if (bullet.intersects(enemy)) {
				// Apply damage to enemy
				if (enemy.takeDamage(bullet.damage)) {
					enemy.destroy();
					enemies.splice(j, 1);
				}
				// Remove bullet
				bullet.destroy();
				playerBullets.splice(i, 1);
				hitEnemy = true;
				break;
			}
		}
		// Check for collision with boss
		if (!hitEnemy && boss && bullet.intersects(boss)) {
			boss.takeDamage(bullet.damage);
			// Remove bullet
			bullet.destroy();
			playerBullets.splice(i, 1);
			// Check if boss is defeated
			if (boss.health <= 0) {
				boss.destroy();
				boss = null;
				removeBossHealthBar();
				waveDelay = 180; // Delay before next wave
			}
		}
	}
	// Update enemy bullets
	for (var i = enemyBullets.length - 1; i >= 0; i--) {
		var bullet = enemyBullets[i];
		// Remove bullets that go off screen
		if (bullet.y > 2732 + 50) {
			bullet.destroy();
			enemyBullets.splice(i, 1);
			continue;
		}
		// Check for collision with player
		if (player && bullet.intersects(player)) {
			player.takeDamage();
			updateLives();
			// Remove bullet
			bullet.destroy();
			enemyBullets.splice(i, 1);
		}
	}
	// Update enemies
	for (var i = enemies.length - 1; i >= 0; i--) {
		var enemy = enemies[i];
		// Remove enemies that go off screen
		if (enemy.y > 2732 + 100) {
			enemy.destroy();
			enemies.splice(i, 1);
			continue;
		}
		// Check for collision with player
		if (player && enemy.intersects(player)) {
			player.takeDamage();
			updateLives();
			// Remove enemy
			createExplosion(enemy.x, enemy.y);
			LK.getSound('explosion').play();
			enemy.destroy();
			enemies.splice(i, 1);
		}
	}
	// Update power-ups
	for (var i = powerUps.length - 1; i >= 0; i--) {
		var powerUp = powerUps[i];
		// Remove power-ups that go off screen
		if (powerUp.y > 2732 + 50) {
			powerUp.destroy();
			powerUps.splice(i, 1);
			continue;
		}
		// Check for collision with player
		if (player && powerUp.intersects(player)) {
			if (powerUp.collect()) {
				powerUp.destroy();
				powerUps.splice(i, 1);
			}
		}
	}
	// Update explosions
	for (var i = explosions.length - 1; i >= 0; i--) {
		var explosion = explosions[i];
		if (explosion.update()) {
			explosions.splice(i, 1);
		}
	}
	// Check if all enemies are defeated
	if (enemies.length === 0 && !boss) {
		if (waveDelay > 0) {
			waveDelay--;
		} else {
			startNewWave();
		}
	}
	// Update high score
	if (LK.getScore() > storage.highScore) {
		storage.highScore = LK.getScore();
		highScoreTxt.setText('High Score: ' + storage.highScore);
	}
};
// Initialize game with a start message
var startText = null;
var startText = new Text2('Tap to Start', {
	size: 100,
	fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
// Remove start text when game starts
LK.on('tick', function () {
	if (gameStarted && startText && startText.parent) {
		LK.gui.center.removeChild(startText);
	}
});
 A space ship. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows standing
 
 Evil alien spaceship red. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 Shield. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 An evil alien spaceship big. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
 
 Realistic space. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows