User prompt
Fix error
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'LK.playSound('shoot');' Line Number: 578
User prompt
Fix it so the sound assets work again
User prompt
Add a cool background with visual effects
User prompt
Create a cool startscreen ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Space Defender: Asteroid Rush
Initial prompt
Create me a cool mobile game
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Asteroid = Container.expand(function () {
	var self = Container.call(this);
	var size = 1 + Math.random() * 2; // Size between 1 and 3
	var asteroid = self.attachAsset('asteroid', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: size,
		scaleY: size
	});
	self.size = size;
	self.speedX = (Math.random() - 0.5) * 6;
	self.speedY = 3 + Math.random() * 5;
	self.rotationSpeed = (Math.random() - 0.5) * 0.05;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		self.rotation += self.rotationSpeed;
		// Check if asteroid is outside the screen bounds
		if (self.y > 2732 + asteroid.height) {
			self.markForRemoval = true;
		}
		// Bounce off the sides
		if (self.x < 0 || self.x > 2048) {
			self.speedX = -self.speedX;
		}
	};
	return self;
});
var Background = Container.expand(function () {
	var self = Container.call(this);
	// Create multiple layers of parallax stars
	var starLayers = [];
	var starCounts = [150, 100, 75]; // Different numbers of stars for each layer
	var starSpeeds = [0.3, 0.7, 1.5]; // Different speeds for each layer
	// Create nebulae (colored clouds)
	var nebulae = [];
	var nebulaColors = [0x3498db, 0x9b59b6, 0x2ecc71, 0xe74c3c];
	for (var l = 0; l < starLayers.length; l++) {
		starLayers[l] = [];
	}
	// Create stars for each layer
	for (var l = 0; l < starCounts.length; l++) {
		var layer = [];
		for (var i = 0; i < starCounts[l]; i++) {
			var brightness = 0.3 + Math.random() * 0.7;
			var size = (0.1 + Math.random() * 0.3) * (1 + l * 0.5);
			var star = LK.getAsset('powerUp', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: size,
				scaleY: size,
				alpha: brightness,
				tint: 0xFFFFFF
			});
			star.x = Math.random() * 2048;
			star.y = Math.random() * 2732;
			star.speed = starSpeeds[l];
			star.twinkleSpeed = 0.01 + Math.random() * 0.03;
			star.twinkleDirection = Math.random() > 0.5 ? 1 : -1;
			star.twinkleRange = 0.2 + Math.random() * 0.3;
			star.twinkleOffset = Math.random() * Math.PI * 2;
			star.baseAlpha = brightness;
			layer.push(star);
			self.addChild(star);
		}
		starLayers.push(layer);
	}
	// Create nebulae (colored particle clouds)
	for (var i = 0; i < 5; i++) {
		var nebulaColor = nebulaColors[Math.floor(Math.random() * nebulaColors.length)];
		var nebulaSize = 3 + Math.random() * 5;
		var nebulaParticles = [];
		var centerX = Math.random() * 2048;
		var centerY = Math.random() * 2732;
		var radius = 100 + Math.random() * 200;
		// Create nebula cloud particles
		for (var j = 0; j < 10; j++) {
			var angle = Math.random() * Math.PI * 2;
			var distance = Math.random() * radius;
			var nebulaPart = LK.getAsset('powerUp', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: nebulaSize,
				scaleY: nebulaSize,
				alpha: 0.02 + Math.random() * 0.1,
				tint: nebulaColor
			});
			nebulaPart.x = centerX + Math.cos(angle) * distance;
			nebulaPart.y = centerY + Math.sin(angle) * distance;
			nebulaPart.speed = 0.1 + Math.random() * 0.2;
			nebulaPart.rotation = Math.random() * Math.PI * 2;
			nebulaPart.rotSpeed = (Math.random() - 0.5) * 0.01;
			nebulaParticles.push(nebulaPart);
			self.addChild(nebulaPart);
		}
		nebulae.push({
			particles: nebulaParticles,
			x: centerX,
			y: centerY,
			speed: 0.2 + Math.random() * 0.3
		});
	}
	// Create shooting stars that randomly appear
	self.lastShootingStar = 0;
	self.createShootingStar = function () {
		var star = LK.getAsset('powerUp', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.2,
			scaleY: 0.2,
			alpha: 0.8,
			tint: 0xFFFFFF
		});
		// Position the shooting star at the edge of the screen
		var startFromLeft = Math.random() > 0.5;
		star.x = startFromLeft ? -10 : 2058;
		star.y = Math.random() * 1366;
		// Set the trajectory
		var angle = Math.PI * 0.25 + Math.random() * Math.PI * 0.25;
		if (!startFromLeft) {
			angle = Math.PI - angle;
		}
		star.speedX = Math.cos(angle) * (10 + Math.random() * 15);
		star.speedY = Math.sin(angle) * (10 + Math.random() * 15);
		star.trailLength = 5;
		star.trail = [];
		for (var i = 0; i < star.trailLength; i++) {
			var trailPart = LK.getAsset('powerUp', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: 0.2 - i * 0.03,
				scaleY: 0.2 - i * 0.03,
				alpha: 0.6 - i * 0.1,
				tint: 0xFFFFFF
			});
			trailPart.x = star.x;
			trailPart.y = star.y;
			star.trail.push(trailPart);
			self.addChild(trailPart);
		}
		self.addChild(star);
		return star;
	};
	self.shootingStars = [];
	self.update = function () {
		// Update twinkle effect for stars
		for (var l = 0; l < starLayers.length; l++) {
			var layer = starLayers[l];
			for (var i = 0; i < layer.length; i++) {
				var star = layer[i];
				// Move stars down for parallax effect
				star.y += star.speed;
				if (star.y > 2732) {
					star.y = 0;
					star.x = Math.random() * 2048;
				}
				// Twinkle effect (oscillating alpha)
				star.alpha = star.baseAlpha + Math.sin(LK.ticks * star.twinkleSpeed + star.twinkleOffset) * star.twinkleRange;
			}
		}
		// Update nebulae
		for (var i = 0; i < nebulae.length; i++) {
			var nebula = nebulae[i];
			// Move nebula slowly down
			nebula.y += nebula.speed;
			// Wrap around when off screen
			if (nebula.y > 2732 + 300) {
				nebula.y = -300;
				nebula.x = Math.random() * 2048;
			}
			// Update all particles in this nebula
			for (var j = 0; j < nebula.particles.length; j++) {
				var part = nebula.particles[j];
				part.y += nebula.speed;
				part.rotation += part.rotSpeed;
				// Slowly rotate around the center
				var dx = part.x - nebula.x;
				var dy = part.y - nebula.y;
				var angle = Math.atan2(dy, dx);
				var dist = Math.sqrt(dx * dx + dy * dy);
				angle += 0.001;
				part.x = nebula.x + Math.cos(angle) * dist;
				part.y = nebula.y + Math.sin(angle) * dist;
			}
		}
		// Occasional shooting stars
		if (LK.ticks - self.lastShootingStar > 300 && Math.random() < 0.02) {
			self.shootingStars.push(self.createShootingStar());
			self.lastShootingStar = LK.ticks;
		}
		// Update shooting stars
		for (var i = self.shootingStars.length - 1; i >= 0; i--) {
			var ss = self.shootingStars[i];
			// Move the star
			ss.x += ss.speedX;
			ss.y += ss.speedY;
			// Update trail
			for (var j = ss.trail.length - 1; j >= 0; j--) {
				if (j === 0) {
					ss.trail[j].x = ss.x - ss.speedX;
					ss.trail[j].y = ss.y - ss.speedY;
				} else {
					ss.trail[j].x = ss.trail[j - 1].x - ss.speedX * 0.5;
					ss.trail[j].y = ss.trail[j - 1].y - ss.speedY * 0.5;
				}
			}
			// Remove if off screen
			if (ss.x < -50 || ss.x > 2098 || ss.y < -50 || ss.y > 2782) {
				for (var j = 0; j < ss.trail.length; j++) {
					self.removeChild(ss.trail[j]);
				}
				self.removeChild(ss);
				self.shootingStars.splice(i, 1);
			}
		}
	};
	return self;
});
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bullet = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -15; // Negative because bullets move upward
	self.update = function () {
		self.y += self.speed;
		// Check if bullet is outside the screen bounds
		if (self.y < -bullet.height) {
			self.markForRemoval = true;
		}
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	self.type = Math.random() < 0.5 ? 'shield' : 'multiShot';
	var powerUp = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: self.type === 'shield' ? 0x2ecc71 : 0xf1c40f
	});
	self.speed = 3 + Math.random() * 2;
	self.update = function () {
		self.y += self.speed;
		self.rotation += 0.02;
		// Check if power-up is outside the screen bounds
		if (self.y > 2732 + powerUp.height) {
			self.markForRemoval = true;
		}
	};
	return self;
});
var Spaceship = Container.expand(function () {
	var self = Container.call(this);
	var ship = self.attachAsset('spaceship', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.shield = false;
	self.shieldTime = 0;
	self.shieldGraphics = null;
	self.multiShot = false;
	self.multiShotTime = 0;
	self.activateShield = function (duration) {
		self.shield = true;
		self.shieldTime = duration;
		if (!self.shieldGraphics) {
			self.shieldGraphics = self.attachAsset('shield', {
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.5
			});
		} else {
			self.shieldGraphics.alpha = 0.5;
		}
	};
	self.activateMultiShot = function (duration) {
		self.multiShot = true;
		self.multiShotTime = duration;
	};
	self.update = function () {
		if (self.shield) {
			self.shieldTime--;
			if (self.shieldTime <= 0) {
				self.shield = false;
				if (self.shieldGraphics) {
					self.shieldGraphics.alpha = 0;
				}
			}
		}
		if (self.multiShot) {
			self.multiShotTime--;
			if (self.multiShotTime <= 0) {
				self.multiShot = false;
			}
		}
	};
	return self;
});
var StartScreen = Container.expand(function () {
	var self = Container.call(this);
	// Game title
	var titleText = new Text2('SPACE DEFENDER', {
		size: 120,
		fill: 0x4fc3f7
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = 2048 / 2;
	titleText.y = 2732 / 3;
	self.addChild(titleText);
	// Subtitle
	var subtitleText = new Text2('ASTEROID RUSH', {
		size: 80,
		fill: 0xb3e5fc
	});
	subtitleText.anchor.set(0.5, 0.5);
	subtitleText.x = 2048 / 2;
	subtitleText.y = titleText.y + 120;
	self.addChild(subtitleText);
	// Instructions
	var instructionsText = new Text2('DRAG TO MOVE • TAP TO SHOOT', {
		size: 50,
		fill: 0xFFFFFF
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = 2048 / 2;
	instructionsText.y = 2732 / 2 + 200;
	self.addChild(instructionsText);
	// Animated star field background
	var stars = [];
	for (var i = 0; i < 100; i++) {
		var star = LK.getAsset('powerUp', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.1 + Math.random() * 0.3,
			scaleY: 0.1 + Math.random() * 0.3,
			alpha: 0.2 + Math.random() * 0.8,
			tint: 0xFFFFFF
		});
		star.x = Math.random() * 2048;
		star.y = Math.random() * 2732;
		star.speed = 0.5 + Math.random() * 2;
		stars.push(star);
		self.addChild(star);
	}
	// Small spaceship preview
	var shipPreview = LK.getAsset('spaceship', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	shipPreview.x = 2048 / 2;
	shipPreview.y = 2732 / 2 + 400;
	self.addChild(shipPreview);
	// Animate title with pulsing effect
	tween(titleText, {
		scaleX: 1.1,
		scaleY: 1.1
	}, {
		duration: 1500,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(titleText, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 1500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					// Restart the animation
					tween(titleText, {
						scaleX: 1.1,
						scaleY: 1.1
					}, {
						duration: 1500,
						easing: tween.easeInOut
					});
				}
			});
		}
	});
	// Rotate ship preview
	tween(shipPreview, {
		rotation: Math.PI * 2
	}, {
		duration: 8000,
		easing: tween.linear,
		onFinish: function onFinish() {
			shipPreview.rotation = 0;
			// Restart the rotation
			tween(shipPreview, {
				rotation: Math.PI * 2
			}, {
				duration: 8000,
				easing: tween.linear
			});
		}
	});
	self.update = function () {
		// Animate stars
		for (var i = 0; i < stars.length; i++) {
			stars[i].y += stars[i].speed;
			if (stars[i].y > 2732) {
				stars[i].y = 0;
				stars[i].x = Math.random() * 2048;
			}
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000022
});
/**** 
* Game Code
****/ 
// Game variables
var spaceship;
var asteroids = [];
var bullets = [];
var powerUps = [];
var lastShot = 0;
var shotCooldown = 15; // Frames between shots
var score = 0;
var level = 1;
var gameStarted = false;
var dragMode = false;
var highScore = storage.highScore || 0;
// Create animated background
var background = new Background();
game.addChild(background);
var startScreen = new StartScreen();
game.addChild(startScreen);
// Set a space background
game.setBackgroundColor(0x000022);
// Initialize UI elements
var scoreTxt = new Text2('SCORE: 0', {
	size: 50,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -200;
scoreTxt.y = 20;
var levelTxt = new Text2('LEVEL: 1', {
	size: 50,
	fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 20;
var highScoreTxt = new Text2('HIGH SCORE: ' + highScore, {
	size: 50,
	fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -10;
highScoreTxt.y = 80;
// Create start message text
var startTxt = new Text2('TAP ANYWHERE TO START', {
	size: 80,
	fill: 0xFFFF00
});
startTxt.anchor.set(0.5, 0.5);
startTxt.y = 150;
LK.gui.center.addChild(startTxt);
// Animate the start text
function pulseStartText() {
	tween(startTxt, {
		alpha: 0.3
	}, {
		duration: 800,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(startTxt, {
				alpha: 1.0
			}, {
				duration: 800,
				easing: tween.easeInOut,
				onFinish: pulseStartText
			});
		}
	});
}
pulseStartText();
// Initialize spaceship
function initializeGame() {
	// Play background music
	LK.playMusic('gameMusic');
	// Create spaceship
	spaceship = new Spaceship();
	spaceship.x = 2048 / 2;
	spaceship.y = 2732 - 200;
	game.addChild(spaceship);
	// Reset game state
	asteroids = [];
	bullets = [];
	powerUps = [];
	lastShot = 0;
	score = 0;
	level = 1;
	LK.setScore(0);
	// Update UI
	scoreTxt.setText('SCORE: 0');
	levelTxt.setText('LEVEL: 1');
	highScoreTxt.setText('HIGH SCORE: ' + highScore);
}
// Create a new asteroid
function createAsteroid() {
	var asteroid = new Asteroid();
	asteroid.x = Math.random() * 2048;
	asteroid.y = -100;
	asteroids.push(asteroid);
	game.addChild(asteroid);
}
// Create a new power-up
function createPowerUp() {
	var powerUp = new PowerUp();
	powerUp.x = 100 + Math.random() * (2048 - 200);
	powerUp.y = -50;
	powerUps.push(powerUp);
	game.addChild(powerUp);
}
// Fire bullets from the spaceship
function fireBullet() {
	if (LK.ticks - lastShot < shotCooldown) {
		return;
	}
	lastShot = LK.ticks;
	if (spaceship.multiShot) {
		// Create 3 bullets when multi-shot is active
		for (var i = -1; i <= 1; i++) {
			var bullet = new Bullet();
			bullet.x = spaceship.x + i * 30;
			bullet.y = spaceship.y - 30;
			bullets.push(bullet);
			game.addChild(bullet);
		}
	} else {
		// Create a single bullet
		var bullet = new Bullet();
		bullet.x = spaceship.x;
		bullet.y = spaceship.y - 30;
		bullets.push(bullet);
		game.addChild(bullet);
	}
	// Play shoot sound
	LK.getSound('shoot').play();
}
// Handle collisions between game objects
function handleCollisions() {
	// Check bullet-asteroid collisions
	for (var i = bullets.length - 1; i >= 0; i--) {
		for (var j = asteroids.length - 1; j >= 0; j--) {
			if (bullets[i] && asteroids[j] && bullets[i].intersects(asteroids[j])) {
				// Increase score based on asteroid size (smaller = harder to hit = more points)
				var pointsGained = Math.floor(10 / asteroids[j].size);
				score += pointsGained;
				LK.setScore(score);
				scoreTxt.setText('SCORE: ' + score);
				// Play explosion sound
				LK.getSound('explosion').play();
				// Flash effect on hit
				LK.effects.flashObject(asteroids[j], 0xff0000, 200);
				// Remove bullet and asteroid
				bullets[i].markForRemoval = true;
				asteroids[j].markForRemoval = true;
				// Break big asteroids into smaller ones
				if (asteroids[j].size > 1.5) {
					for (var k = 0; k < 2; k++) {
						var newAsteroid = new Asteroid();
						newAsteroid.size = asteroids[j].size * 0.6;
						newAsteroid.x = asteroids[j].x + (Math.random() - 0.5) * 40;
						newAsteroid.y = asteroids[j].y + (Math.random() - 0.5) * 40;
						asteroids.push(newAsteroid);
						game.addChild(newAsteroid);
					}
				}
				// Randomly spawn power-up (5% chance)
				if (Math.random() < 0.05) {
					var powerUp = new PowerUp();
					powerUp.x = asteroids[j].x;
					powerUp.y = asteroids[j].y;
					powerUps.push(powerUp);
					game.addChild(powerUp);
				}
				break;
			}
		}
	}
	// Check spaceship-asteroid collisions
	if (spaceship) {
		for (var i = asteroids.length - 1; i >= 0; i--) {
			if (spaceship.intersects(asteroids[i])) {
				if (spaceship.shield) {
					// If the spaceship has a shield, destroy the asteroid but don't end the game
					asteroids[i].markForRemoval = true;
					LK.effects.flashObject(spaceship.shieldGraphics, 0xffffff, 300);
					LK.getSound('explosion').play();
				} else {
					// Game over
					LK.effects.flashScreen(0xff0000, 800);
					// Update high score if needed
					if (score > highScore) {
						highScore = score;
						storage.highScore = highScore;
					}
					// Show game over
					LK.showGameOver();
					return true;
				}
			}
		}
	}
	// Check spaceship-powerup collisions
	if (spaceship) {
		for (var i = powerUps.length - 1; i >= 0; i--) {
			if (spaceship.intersects(powerUps[i])) {
				// Activate power-up effect
				if (powerUps[i].type === 'shield') {
					spaceship.activateShield(600); // 10 seconds at 60 FPS
				} else if (powerUps[i].type === 'multiShot') {
					spaceship.activateMultiShot(600); // 10 seconds at 60 FPS
				}
				// Play power-up sound
				LK.getSound('powerup').play();
				// Flash effect
				LK.effects.flashObject(spaceship, 0xffffff, 300);
				// Remove power-up
				powerUps[i].markForRemoval = true;
			}
		}
	}
	return false;
}
// Clean up game objects marked for removal
function cleanupObjects() {
	for (var i = bullets.length - 1; i >= 0; i--) {
		if (bullets[i].markForRemoval) {
			bullets[i].destroy();
			bullets.splice(i, 1);
		}
	}
	for (var i = asteroids.length - 1; i >= 0; i--) {
		if (asteroids[i].markForRemoval) {
			asteroids[i].destroy();
			asteroids.splice(i, 1);
		}
	}
	for (var i = powerUps.length - 1; i >= 0; i--) {
		if (powerUps[i].markForRemoval) {
			powerUps[i].destroy();
			powerUps.splice(i, 1);
		}
	}
}
// Main game loop
game.update = function () {
	// Always update background for continuous animation
	background.update();
	if (!gameStarted) {
		startScreen.update();
		return;
	}
	// Update spaceship
	if (spaceship) {
		spaceship.update();
	}
	// Update bullets
	for (var i = 0; i < bullets.length; i++) {
		bullets[i].update();
	}
	// Update asteroids
	for (var i = 0; i < asteroids.length; i++) {
		asteroids[i].update();
	}
	// Update power-ups
	for (var i = 0; i < powerUps.length; i++) {
		powerUps[i].update();
	}
	// Create asteroids based on level and time
	if (LK.ticks % Math.max(60 - level * 5, 15) === 0) {
		createAsteroid();
	}
	// Create power-ups rarely
	if (LK.ticks % 600 === 0) {
		createPowerUp();
	}
	// Handle collisions
	var gameOver = handleCollisions();
	if (gameOver) {
		return;
	}
	// Clean up objects
	cleanupObjects();
	// Level up based on score
	var newLevel = Math.floor(score / 100) + 1;
	if (newLevel > level) {
		level = newLevel;
		levelTxt.setText('LEVEL: ' + level);
	}
	// Auto-fire if in drag mode
	if (dragMode && LK.ticks % 10 === 0) {
		fireBullet();
	}
};
// Game input handlers
function handleMove(x, y, obj) {
	if (!gameStarted) {
		return;
	}
	if (dragMode && spaceship) {
		spaceship.x = x;
		spaceship.y = y;
	}
}
game.down = function (x, y, obj) {
	if (!gameStarted) {
		// Start the game on first tap
		gameStarted = true;
		initializeGame();
		// Remove the start screen and text
		game.removeChild(startScreen);
		LK.gui.center.removeChild(startTxt);
		// Play a transition effect
		LK.effects.flashScreen(0xFFFFFF, 500);
		return;
	}
	// Start dragging the spaceship
	dragMode = true;
	// Update spaceship position immediately
	if (spaceship) {
		spaceship.x = x;
		spaceship.y = y;
	}
	// Fire a bullet
	fireBullet();
};
game.up = function (x, y, obj) {
	dragMode = false;
};
game.move = handleMove; /**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
var Asteroid = Container.expand(function () {
	var self = Container.call(this);
	var size = 1 + Math.random() * 2; // Size between 1 and 3
	var asteroid = self.attachAsset('asteroid', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: size,
		scaleY: size
	});
	self.size = size;
	self.speedX = (Math.random() - 0.5) * 6;
	self.speedY = 3 + Math.random() * 5;
	self.rotationSpeed = (Math.random() - 0.5) * 0.05;
	self.update = function () {
		self.x += self.speedX;
		self.y += self.speedY;
		self.rotation += self.rotationSpeed;
		// Check if asteroid is outside the screen bounds
		if (self.y > 2732 + asteroid.height) {
			self.markForRemoval = true;
		}
		// Bounce off the sides
		if (self.x < 0 || self.x > 2048) {
			self.speedX = -self.speedX;
		}
	};
	return self;
});
var Background = Container.expand(function () {
	var self = Container.call(this);
	// Create multiple layers of parallax stars
	var starLayers = [];
	var starCounts = [150, 100, 75]; // Different numbers of stars for each layer
	var starSpeeds = [0.3, 0.7, 1.5]; // Different speeds for each layer
	// Create nebulae (colored clouds)
	var nebulae = [];
	var nebulaColors = [0x3498db, 0x9b59b6, 0x2ecc71, 0xe74c3c];
	for (var l = 0; l < starLayers.length; l++) {
		starLayers[l] = [];
	}
	// Create stars for each layer
	for (var l = 0; l < starCounts.length; l++) {
		var layer = [];
		for (var i = 0; i < starCounts[l]; i++) {
			var brightness = 0.3 + Math.random() * 0.7;
			var size = (0.1 + Math.random() * 0.3) * (1 + l * 0.5);
			var star = LK.getAsset('powerUp', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: size,
				scaleY: size,
				alpha: brightness,
				tint: 0xFFFFFF
			});
			star.x = Math.random() * 2048;
			star.y = Math.random() * 2732;
			star.speed = starSpeeds[l];
			star.twinkleSpeed = 0.01 + Math.random() * 0.03;
			star.twinkleDirection = Math.random() > 0.5 ? 1 : -1;
			star.twinkleRange = 0.2 + Math.random() * 0.3;
			star.twinkleOffset = Math.random() * Math.PI * 2;
			star.baseAlpha = brightness;
			layer.push(star);
			self.addChild(star);
		}
		starLayers.push(layer);
	}
	// Create nebulae (colored particle clouds)
	for (var i = 0; i < 5; i++) {
		var nebulaColor = nebulaColors[Math.floor(Math.random() * nebulaColors.length)];
		var nebulaSize = 3 + Math.random() * 5;
		var nebulaParticles = [];
		var centerX = Math.random() * 2048;
		var centerY = Math.random() * 2732;
		var radius = 100 + Math.random() * 200;
		// Create nebula cloud particles
		for (var j = 0; j < 10; j++) {
			var angle = Math.random() * Math.PI * 2;
			var distance = Math.random() * radius;
			var nebulaPart = LK.getAsset('powerUp', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: nebulaSize,
				scaleY: nebulaSize,
				alpha: 0.02 + Math.random() * 0.1,
				tint: nebulaColor
			});
			nebulaPart.x = centerX + Math.cos(angle) * distance;
			nebulaPart.y = centerY + Math.sin(angle) * distance;
			nebulaPart.speed = 0.1 + Math.random() * 0.2;
			nebulaPart.rotation = Math.random() * Math.PI * 2;
			nebulaPart.rotSpeed = (Math.random() - 0.5) * 0.01;
			nebulaParticles.push(nebulaPart);
			self.addChild(nebulaPart);
		}
		nebulae.push({
			particles: nebulaParticles,
			x: centerX,
			y: centerY,
			speed: 0.2 + Math.random() * 0.3
		});
	}
	// Create shooting stars that randomly appear
	self.lastShootingStar = 0;
	self.createShootingStar = function () {
		var star = LK.getAsset('powerUp', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.2,
			scaleY: 0.2,
			alpha: 0.8,
			tint: 0xFFFFFF
		});
		// Position the shooting star at the edge of the screen
		var startFromLeft = Math.random() > 0.5;
		star.x = startFromLeft ? -10 : 2058;
		star.y = Math.random() * 1366;
		// Set the trajectory
		var angle = Math.PI * 0.25 + Math.random() * Math.PI * 0.25;
		if (!startFromLeft) {
			angle = Math.PI - angle;
		}
		star.speedX = Math.cos(angle) * (10 + Math.random() * 15);
		star.speedY = Math.sin(angle) * (10 + Math.random() * 15);
		star.trailLength = 5;
		star.trail = [];
		for (var i = 0; i < star.trailLength; i++) {
			var trailPart = LK.getAsset('powerUp', {
				anchorX: 0.5,
				anchorY: 0.5,
				scaleX: 0.2 - i * 0.03,
				scaleY: 0.2 - i * 0.03,
				alpha: 0.6 - i * 0.1,
				tint: 0xFFFFFF
			});
			trailPart.x = star.x;
			trailPart.y = star.y;
			star.trail.push(trailPart);
			self.addChild(trailPart);
		}
		self.addChild(star);
		return star;
	};
	self.shootingStars = [];
	self.update = function () {
		// Update twinkle effect for stars
		for (var l = 0; l < starLayers.length; l++) {
			var layer = starLayers[l];
			for (var i = 0; i < layer.length; i++) {
				var star = layer[i];
				// Move stars down for parallax effect
				star.y += star.speed;
				if (star.y > 2732) {
					star.y = 0;
					star.x = Math.random() * 2048;
				}
				// Twinkle effect (oscillating alpha)
				star.alpha = star.baseAlpha + Math.sin(LK.ticks * star.twinkleSpeed + star.twinkleOffset) * star.twinkleRange;
			}
		}
		// Update nebulae
		for (var i = 0; i < nebulae.length; i++) {
			var nebula = nebulae[i];
			// Move nebula slowly down
			nebula.y += nebula.speed;
			// Wrap around when off screen
			if (nebula.y > 2732 + 300) {
				nebula.y = -300;
				nebula.x = Math.random() * 2048;
			}
			// Update all particles in this nebula
			for (var j = 0; j < nebula.particles.length; j++) {
				var part = nebula.particles[j];
				part.y += nebula.speed;
				part.rotation += part.rotSpeed;
				// Slowly rotate around the center
				var dx = part.x - nebula.x;
				var dy = part.y - nebula.y;
				var angle = Math.atan2(dy, dx);
				var dist = Math.sqrt(dx * dx + dy * dy);
				angle += 0.001;
				part.x = nebula.x + Math.cos(angle) * dist;
				part.y = nebula.y + Math.sin(angle) * dist;
			}
		}
		// Occasional shooting stars
		if (LK.ticks - self.lastShootingStar > 300 && Math.random() < 0.02) {
			self.shootingStars.push(self.createShootingStar());
			self.lastShootingStar = LK.ticks;
		}
		// Update shooting stars
		for (var i = self.shootingStars.length - 1; i >= 0; i--) {
			var ss = self.shootingStars[i];
			// Move the star
			ss.x += ss.speedX;
			ss.y += ss.speedY;
			// Update trail
			for (var j = ss.trail.length - 1; j >= 0; j--) {
				if (j === 0) {
					ss.trail[j].x = ss.x - ss.speedX;
					ss.trail[j].y = ss.y - ss.speedY;
				} else {
					ss.trail[j].x = ss.trail[j - 1].x - ss.speedX * 0.5;
					ss.trail[j].y = ss.trail[j - 1].y - ss.speedY * 0.5;
				}
			}
			// Remove if off screen
			if (ss.x < -50 || ss.x > 2098 || ss.y < -50 || ss.y > 2782) {
				for (var j = 0; j < ss.trail.length; j++) {
					self.removeChild(ss.trail[j]);
				}
				self.removeChild(ss);
				self.shootingStars.splice(i, 1);
			}
		}
	};
	return self;
});
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bullet = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.speed = -15; // Negative because bullets move upward
	self.update = function () {
		self.y += self.speed;
		// Check if bullet is outside the screen bounds
		if (self.y < -bullet.height) {
			self.markForRemoval = true;
		}
	};
	return self;
});
var PowerUp = Container.expand(function () {
	var self = Container.call(this);
	self.type = Math.random() < 0.5 ? 'shield' : 'multiShot';
	var powerUp = self.attachAsset('powerUp', {
		anchorX: 0.5,
		anchorY: 0.5,
		tint: self.type === 'shield' ? 0x2ecc71 : 0xf1c40f
	});
	self.speed = 3 + Math.random() * 2;
	self.update = function () {
		self.y += self.speed;
		self.rotation += 0.02;
		// Check if power-up is outside the screen bounds
		if (self.y > 2732 + powerUp.height) {
			self.markForRemoval = true;
		}
	};
	return self;
});
var Spaceship = Container.expand(function () {
	var self = Container.call(this);
	var ship = self.attachAsset('spaceship', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.shield = false;
	self.shieldTime = 0;
	self.shieldGraphics = null;
	self.multiShot = false;
	self.multiShotTime = 0;
	self.activateShield = function (duration) {
		self.shield = true;
		self.shieldTime = duration;
		if (!self.shieldGraphics) {
			self.shieldGraphics = self.attachAsset('shield', {
				anchorX: 0.5,
				anchorY: 0.5,
				alpha: 0.5
			});
		} else {
			self.shieldGraphics.alpha = 0.5;
		}
	};
	self.activateMultiShot = function (duration) {
		self.multiShot = true;
		self.multiShotTime = duration;
	};
	self.update = function () {
		if (self.shield) {
			self.shieldTime--;
			if (self.shieldTime <= 0) {
				self.shield = false;
				if (self.shieldGraphics) {
					self.shieldGraphics.alpha = 0;
				}
			}
		}
		if (self.multiShot) {
			self.multiShotTime--;
			if (self.multiShotTime <= 0) {
				self.multiShot = false;
			}
		}
	};
	return self;
});
var StartScreen = Container.expand(function () {
	var self = Container.call(this);
	// Game title
	var titleText = new Text2('SPACE DEFENDER', {
		size: 120,
		fill: 0x4fc3f7
	});
	titleText.anchor.set(0.5, 0.5);
	titleText.x = 2048 / 2;
	titleText.y = 2732 / 3;
	self.addChild(titleText);
	// Subtitle
	var subtitleText = new Text2('ASTEROID RUSH', {
		size: 80,
		fill: 0xb3e5fc
	});
	subtitleText.anchor.set(0.5, 0.5);
	subtitleText.x = 2048 / 2;
	subtitleText.y = titleText.y + 120;
	self.addChild(subtitleText);
	// Instructions
	var instructionsText = new Text2('DRAG TO MOVE • TAP TO SHOOT', {
		size: 50,
		fill: 0xFFFFFF
	});
	instructionsText.anchor.set(0.5, 0.5);
	instructionsText.x = 2048 / 2;
	instructionsText.y = 2732 / 2 + 200;
	self.addChild(instructionsText);
	// Animated star field background
	var stars = [];
	for (var i = 0; i < 100; i++) {
		var star = LK.getAsset('powerUp', {
			anchorX: 0.5,
			anchorY: 0.5,
			scaleX: 0.1 + Math.random() * 0.3,
			scaleY: 0.1 + Math.random() * 0.3,
			alpha: 0.2 + Math.random() * 0.8,
			tint: 0xFFFFFF
		});
		star.x = Math.random() * 2048;
		star.y = Math.random() * 2732;
		star.speed = 0.5 + Math.random() * 2;
		stars.push(star);
		self.addChild(star);
	}
	// Small spaceship preview
	var shipPreview = LK.getAsset('spaceship', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 2,
		scaleY: 2
	});
	shipPreview.x = 2048 / 2;
	shipPreview.y = 2732 / 2 + 400;
	self.addChild(shipPreview);
	// Animate title with pulsing effect
	tween(titleText, {
		scaleX: 1.1,
		scaleY: 1.1
	}, {
		duration: 1500,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(titleText, {
				scaleX: 1.0,
				scaleY: 1.0
			}, {
				duration: 1500,
				easing: tween.easeInOut,
				onFinish: function onFinish() {
					// Restart the animation
					tween(titleText, {
						scaleX: 1.1,
						scaleY: 1.1
					}, {
						duration: 1500,
						easing: tween.easeInOut
					});
				}
			});
		}
	});
	// Rotate ship preview
	tween(shipPreview, {
		rotation: Math.PI * 2
	}, {
		duration: 8000,
		easing: tween.linear,
		onFinish: function onFinish() {
			shipPreview.rotation = 0;
			// Restart the rotation
			tween(shipPreview, {
				rotation: Math.PI * 2
			}, {
				duration: 8000,
				easing: tween.linear
			});
		}
	});
	self.update = function () {
		// Animate stars
		for (var i = 0; i < stars.length; i++) {
			stars[i].y += stars[i].speed;
			if (stars[i].y > 2732) {
				stars[i].y = 0;
				stars[i].x = Math.random() * 2048;
			}
		}
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000022
});
/**** 
* Game Code
****/ 
// Game variables
var spaceship;
var asteroids = [];
var bullets = [];
var powerUps = [];
var lastShot = 0;
var shotCooldown = 15; // Frames between shots
var score = 0;
var level = 1;
var gameStarted = false;
var dragMode = false;
var highScore = storage.highScore || 0;
// Create animated background
var background = new Background();
game.addChild(background);
var startScreen = new StartScreen();
game.addChild(startScreen);
// Set a space background
game.setBackgroundColor(0x000022);
// Initialize UI elements
var scoreTxt = new Text2('SCORE: 0', {
	size: 50,
	fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -200;
scoreTxt.y = 20;
var levelTxt = new Text2('LEVEL: 1', {
	size: 50,
	fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
levelTxt.y = 20;
var highScoreTxt = new Text2('HIGH SCORE: ' + highScore, {
	size: 50,
	fill: 0xFFFFFF
});
highScoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -10;
highScoreTxt.y = 80;
// Create start message text
var startTxt = new Text2('TAP ANYWHERE TO START', {
	size: 80,
	fill: 0xFFFF00
});
startTxt.anchor.set(0.5, 0.5);
startTxt.y = 150;
LK.gui.center.addChild(startTxt);
// Animate the start text
function pulseStartText() {
	tween(startTxt, {
		alpha: 0.3
	}, {
		duration: 800,
		easing: tween.easeInOut,
		onFinish: function onFinish() {
			tween(startTxt, {
				alpha: 1.0
			}, {
				duration: 800,
				easing: tween.easeInOut,
				onFinish: pulseStartText
			});
		}
	});
}
pulseStartText();
// Initialize spaceship
function initializeGame() {
	// Play background music
	LK.playMusic('gameMusic');
	// Create spaceship
	spaceship = new Spaceship();
	spaceship.x = 2048 / 2;
	spaceship.y = 2732 - 200;
	game.addChild(spaceship);
	// Reset game state
	asteroids = [];
	bullets = [];
	powerUps = [];
	lastShot = 0;
	score = 0;
	level = 1;
	LK.setScore(0);
	// Update UI
	scoreTxt.setText('SCORE: 0');
	levelTxt.setText('LEVEL: 1');
	highScoreTxt.setText('HIGH SCORE: ' + highScore);
}
// Create a new asteroid
function createAsteroid() {
	var asteroid = new Asteroid();
	asteroid.x = Math.random() * 2048;
	asteroid.y = -100;
	asteroids.push(asteroid);
	game.addChild(asteroid);
}
// Create a new power-up
function createPowerUp() {
	var powerUp = new PowerUp();
	powerUp.x = 100 + Math.random() * (2048 - 200);
	powerUp.y = -50;
	powerUps.push(powerUp);
	game.addChild(powerUp);
}
// Fire bullets from the spaceship
function fireBullet() {
	if (LK.ticks - lastShot < shotCooldown) {
		return;
	}
	lastShot = LK.ticks;
	if (spaceship.multiShot) {
		// Create 3 bullets when multi-shot is active
		for (var i = -1; i <= 1; i++) {
			var bullet = new Bullet();
			bullet.x = spaceship.x + i * 30;
			bullet.y = spaceship.y - 30;
			bullets.push(bullet);
			game.addChild(bullet);
		}
	} else {
		// Create a single bullet
		var bullet = new Bullet();
		bullet.x = spaceship.x;
		bullet.y = spaceship.y - 30;
		bullets.push(bullet);
		game.addChild(bullet);
	}
	// Play shoot sound
	LK.getSound('shoot').play();
}
// Handle collisions between game objects
function handleCollisions() {
	// Check bullet-asteroid collisions
	for (var i = bullets.length - 1; i >= 0; i--) {
		for (var j = asteroids.length - 1; j >= 0; j--) {
			if (bullets[i] && asteroids[j] && bullets[i].intersects(asteroids[j])) {
				// Increase score based on asteroid size (smaller = harder to hit = more points)
				var pointsGained = Math.floor(10 / asteroids[j].size);
				score += pointsGained;
				LK.setScore(score);
				scoreTxt.setText('SCORE: ' + score);
				// Play explosion sound
				LK.getSound('explosion').play();
				// Flash effect on hit
				LK.effects.flashObject(asteroids[j], 0xff0000, 200);
				// Remove bullet and asteroid
				bullets[i].markForRemoval = true;
				asteroids[j].markForRemoval = true;
				// Break big asteroids into smaller ones
				if (asteroids[j].size > 1.5) {
					for (var k = 0; k < 2; k++) {
						var newAsteroid = new Asteroid();
						newAsteroid.size = asteroids[j].size * 0.6;
						newAsteroid.x = asteroids[j].x + (Math.random() - 0.5) * 40;
						newAsteroid.y = asteroids[j].y + (Math.random() - 0.5) * 40;
						asteroids.push(newAsteroid);
						game.addChild(newAsteroid);
					}
				}
				// Randomly spawn power-up (5% chance)
				if (Math.random() < 0.05) {
					var powerUp = new PowerUp();
					powerUp.x = asteroids[j].x;
					powerUp.y = asteroids[j].y;
					powerUps.push(powerUp);
					game.addChild(powerUp);
				}
				break;
			}
		}
	}
	// Check spaceship-asteroid collisions
	if (spaceship) {
		for (var i = asteroids.length - 1; i >= 0; i--) {
			if (spaceship.intersects(asteroids[i])) {
				if (spaceship.shield) {
					// If the spaceship has a shield, destroy the asteroid but don't end the game
					asteroids[i].markForRemoval = true;
					LK.effects.flashObject(spaceship.shieldGraphics, 0xffffff, 300);
					LK.getSound('explosion').play();
				} else {
					// Game over
					LK.effects.flashScreen(0xff0000, 800);
					// Update high score if needed
					if (score > highScore) {
						highScore = score;
						storage.highScore = highScore;
					}
					// Show game over
					LK.showGameOver();
					return true;
				}
			}
		}
	}
	// Check spaceship-powerup collisions
	if (spaceship) {
		for (var i = powerUps.length - 1; i >= 0; i--) {
			if (spaceship.intersects(powerUps[i])) {
				// Activate power-up effect
				if (powerUps[i].type === 'shield') {
					spaceship.activateShield(600); // 10 seconds at 60 FPS
				} else if (powerUps[i].type === 'multiShot') {
					spaceship.activateMultiShot(600); // 10 seconds at 60 FPS
				}
				// Play power-up sound
				LK.getSound('powerup').play();
				// Flash effect
				LK.effects.flashObject(spaceship, 0xffffff, 300);
				// Remove power-up
				powerUps[i].markForRemoval = true;
			}
		}
	}
	return false;
}
// Clean up game objects marked for removal
function cleanupObjects() {
	for (var i = bullets.length - 1; i >= 0; i--) {
		if (bullets[i].markForRemoval) {
			bullets[i].destroy();
			bullets.splice(i, 1);
		}
	}
	for (var i = asteroids.length - 1; i >= 0; i--) {
		if (asteroids[i].markForRemoval) {
			asteroids[i].destroy();
			asteroids.splice(i, 1);
		}
	}
	for (var i = powerUps.length - 1; i >= 0; i--) {
		if (powerUps[i].markForRemoval) {
			powerUps[i].destroy();
			powerUps.splice(i, 1);
		}
	}
}
// Main game loop
game.update = function () {
	// Always update background for continuous animation
	background.update();
	if (!gameStarted) {
		startScreen.update();
		return;
	}
	// Update spaceship
	if (spaceship) {
		spaceship.update();
	}
	// Update bullets
	for (var i = 0; i < bullets.length; i++) {
		bullets[i].update();
	}
	// Update asteroids
	for (var i = 0; i < asteroids.length; i++) {
		asteroids[i].update();
	}
	// Update power-ups
	for (var i = 0; i < powerUps.length; i++) {
		powerUps[i].update();
	}
	// Create asteroids based on level and time
	if (LK.ticks % Math.max(60 - level * 5, 15) === 0) {
		createAsteroid();
	}
	// Create power-ups rarely
	if (LK.ticks % 600 === 0) {
		createPowerUp();
	}
	// Handle collisions
	var gameOver = handleCollisions();
	if (gameOver) {
		return;
	}
	// Clean up objects
	cleanupObjects();
	// Level up based on score
	var newLevel = Math.floor(score / 100) + 1;
	if (newLevel > level) {
		level = newLevel;
		levelTxt.setText('LEVEL: ' + level);
	}
	// Auto-fire if in drag mode
	if (dragMode && LK.ticks % 10 === 0) {
		fireBullet();
	}
};
// Game input handlers
function handleMove(x, y, obj) {
	if (!gameStarted) {
		return;
	}
	if (dragMode && spaceship) {
		spaceship.x = x;
		spaceship.y = y;
	}
}
game.down = function (x, y, obj) {
	if (!gameStarted) {
		// Start the game on first tap
		gameStarted = true;
		initializeGame();
		// Remove the start screen and text
		game.removeChild(startScreen);
		LK.gui.center.removeChild(startTxt);
		// Play a transition effect
		LK.effects.flashScreen(0xFFFFFF, 500);
		return;
	}
	// Start dragging the spaceship
	dragMode = true;
	// Update spaceship position immediately
	if (spaceship) {
		spaceship.x = x;
		spaceship.y = y;
	}
	// Fire a bullet
	fireBullet();
};
game.up = function (x, y, obj) {
	dragMode = false;
};
game.move = handleMove;