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;