/**** * 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 asteroidGraphics = self.attachAsset('asteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 }); self.speed = 3; self.rotationSpeed = (Math.random() - 0.5) * 0.1; self.active = true; self.size = 1; self.health = 1; self.value = 10; self.setup = function (size) { self.size = size || 1; if (self.size === 2) { asteroidGraphics.scale.set(1.5); self.health = 2; self.value = 20; } else if (self.size === 3) { asteroidGraphics.scale.set(2); self.health = 3; self.value = 30; } }; self.hit = function () { self.health -= 1; LK.effects.flashObject(self, 0xff0000, 200); if (self.health <= 0) { self.active = false; return true; } return false; }; self.update = function () { self.y += self.speed; self.rotation += self.rotationSpeed; // Off-screen check (below screen) if (self.y > 2732 + 100) { self.active = false; } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.active = true; self.update = function () { self.y += self.speed; // Off-screen check if (self.y < -50) { self.active = false; } }; return self; }); var Earth = Container.expand(function () { var self = Container.call(this); var earthGraphics = self.attachAsset('earth', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.damage = function (amount) { self.health -= amount; if (self.health < 0) { self.health = 0; } // Flash earth red when damaged LK.effects.flashObject(self, 0xff0000, 300); return self.health <= 0; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); var shieldGraphics = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.lives = 3; self.shieldActive = false; self.invulnerable = false; self.multishot = false; self.multishotDuration = 0; self.shieldDuration = 0; self.activateShield = function () { self.shieldActive = true; self.shieldDuration = 300; // 5 seconds (60 fps * 5) shieldGraphics.alpha = 0.6; tween(shieldGraphics, { alpha: 0.6 }, { duration: 300, easing: tween.easeOut }); }; self.deactivateShield = function () { self.shieldActive = false; tween(shieldGraphics, { alpha: 0 }, { duration: 300, easing: tween.easeIn }); }; self.activateMultishot = function () { self.multishot = true; self.multishotDuration = 300; // 5 seconds // Visual indicator - make ship blink red var flashInterval = LK.setInterval(function () { shipGraphics.tint = shipGraphics.tint === 0xFFFFFF ? 0xff9999 : 0xFFFFFF; }, 200); LK.setTimeout(function () { LK.clearInterval(flashInterval); shipGraphics.tint = 0xFFFFFF; }, 5000); }; self.hit = function () { if (self.shieldActive) { self.deactivateShield(); return false; } if (!self.invulnerable) { self.lives--; self.invulnerable = true; // Flash effect LK.effects.flashObject(self, 0xff0000, 500); // Make player semi-transparent while invulnerable shipGraphics.alpha = 0.5; // Make player vulnerable again after 2 seconds LK.setTimeout(function () { self.invulnerable = false; shipGraphics.alpha = 1; }, 2000); return true; } return false; }; self.update = function () { // Update shield duration if (self.shieldActive) { self.shieldDuration--; if (self.shieldDuration <= 0) { self.deactivateShield(); } } // Update multishot duration if (self.multishot) { self.multishotDuration--; if (self.multishotDuration <= 0) { self.multishot = false; } } }; self.down = function (x, y, obj) { // This is handled in game down handler }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.active = true; self.type = "shield"; // Default type self.setup = function (type) { self.type = type || "shield"; // Change color based on type if (self.type === "shield") { powerupGraphics.tint = 0x3498db; // Blue } else if (self.type === "multishot") { powerupGraphics.tint = 0xe74c3c; // Red } else if (self.type === "bomb") { powerupGraphics.tint = 0xf1c40f; // Yellow } }; self.update = function () { self.y += self.speed; // Make it pulse slightly if (LK.ticks % 10 === 0) { tween(powerupGraphics.scale, { x: 1.1, y: 1.1 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(powerupGraphics.scale, { x: 1, y: 1 }, { duration: 300, easing: tween.easeInOut }); } }); } // Off-screen check if (self.y > 2732 + 50) { self.active = false; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var WAVE_DELAY = 180; // 3 seconds between waves var MAX_ASTEROIDS = 10; // Maximum number of asteroids on screen at once var ASTEROID_SPAWN_CHANCE = 0.02; // Chance to spawn a new asteroid each frame when below max var POWERUP_CHANCE = 0.002; // Chance to spawn a powerup each frame // Game variables var player; var earth; var bullets = []; var asteroids = []; var powerups = []; var waveNumber = 1; var waveDelay = 0; var score = 0; var combo = 0; var comboTimer = 0; var dragMode = false; var gameStarted = false; var gameOver = false; // UI elements var scoreTxt; var waveText; var livesText; var earthHealthText; var comboText; var startText; // Initialize game function initGame() { // Set background to space game.setBackgroundColor(0x000033); // Create earth (at bottom center) earth = new Earth(); earth.x = GAME_WIDTH / 2; earth.y = GAME_HEIGHT - 250; game.addChild(earth); // Create player player = new Player(); player.x = GAME_WIDTH / 2; player.y = GAME_HEIGHT - 500; game.addChild(player); // Reset game variables bullets = []; asteroids = []; powerups = []; waveNumber = 1; waveDelay = 120; // 2 second delay before first wave score = 0; combo = 0; comboTimer = 0; // Update LK score LK.setScore(0); // Create score text scoreTxt = new Text2("SCORE: 0", { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); // Create wave text waveText = new Text2("WAVE: 1", { size: 80, fill: 0xFFFFFF }); waveText.anchor.set(1, 0); LK.gui.topLeft.addChild(waveText); // Create lives text livesText = new Text2("SHIELDS: 3", { size: 80, fill: 0xFFFFFF }); livesText.anchor.set(0.5, 0); LK.gui.top.addChild(livesText); // Create earth health text earthHealthText = new Text2("EARTH: 100%", { size: 80, fill: 0xFFFFFF }); earthHealthText.anchor.set(0.5, 0); LK.gui.bottom.addChild(earthHealthText); // Create combo text (initially invisible) comboText = new Text2("COMBO: x1", { size: 100, fill: 0xFFFF00 }); comboText.anchor.set(0.5, 0.5); comboText.x = GAME_WIDTH / 2; comboText.y = GAME_HEIGHT / 2; comboText.alpha = 0; game.addChild(comboText); // Create start text startText = new Text2("TAP TO START", { size: 120, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); LK.gui.center.addChild(startText); // Animate start text pulseStartText(); gameStarted = false; gameOver = false; // Play music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.3, duration: 1000 } }); } function pulseStartText() { tween(startText.scale, { x: 1.1, y: 1.1 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(startText.scale, { x: 1, y: 1 }, { duration: 800, easing: tween.easeInOut, onFinish: pulseStartText }); } }); } function startGame() { gameStarted = true; // Hide start text tween(startText, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { LK.gui.center.removeChild(startText); } }); } // Spawn a new wave of asteroids function spawnWave() { var asteroidCount = Math.min(5 + waveNumber, MAX_ASTEROIDS); var speed = Math.min(4 + waveNumber * 0.5, 12); for (var i = 0; i < asteroidCount; i++) { var size = 1; var random = Math.random(); // Higher chance of larger asteroids in later waves if (waveNumber > 3 && random > 0.7) { size = 2; } if (waveNumber > 7 && random > 0.9) { size = 3; } spawnAsteroid(size, speed); } // Show wave number waveText.setText("WAVE: " + waveNumber); var waveAnnouncement = new Text2("WAVE " + waveNumber, { size: 150, fill: 0xFFFF00 }); waveAnnouncement.anchor.set(0.5, 0.5); waveAnnouncement.x = GAME_WIDTH / 2; waveAnnouncement.y = GAME_HEIGHT / 2; game.addChild(waveAnnouncement); // Animate wave announcement tween(waveAnnouncement.scale, { x: 1.5, y: 1.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { tween(waveAnnouncement, { alpha: 0 }, { duration: 500, easing: tween.easeIn, onFinish: function onFinish() { game.removeChild(waveAnnouncement); } }); } }); waveNumber++; } // Spawn a single asteroid function spawnAsteroid(size, speed) { var asteroid = new Asteroid(); asteroid.x = Math.random() * (GAME_WIDTH - 100) + 50; asteroid.y = -100; asteroid.speed = Math.min(speed || 2, 2); asteroid.setup(size || 1); asteroids.push(asteroid); game.addChild(asteroid); return asteroid; } // Spawn a power-up function spawnPowerup() { var powerup = new PowerUp(); powerup.x = Math.random() * (GAME_WIDTH - 100) + 50; powerup.y = -100; // Choose random power-up type var random = Math.random(); if (random < 0.4) { powerup.setup("shield"); } else if (random < 0.8) { powerup.setup("multishot"); } else { powerup.setup("bomb"); } powerups.push(powerup); game.addChild(powerup); } // Fire bullets from player function fireBullet() { if (!gameStarted || gameOver) { return; } // Play sound LK.getSound('shoot').play(); if (player.multishot) { // Fire 3 bullets in a spread for (var i = -1; i <= 1; i++) { var bullet = new Bullet(); bullet.x = player.x + i * 40; bullet.y = player.y - 50; bullets.push(bullet); game.addChild(bullet); } } else { // Fire single bullet var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y - 50; bullets.push(bullet); game.addChild(bullet); } } // Check collisions between game objects function checkCollisions() { // Check bullet-asteroid collisions for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (!bullet.active) { continue; } for (var j = asteroids.length - 1; j >= 0; j--) { var asteroid = asteroids[j]; if (!asteroid.active) { continue; } if (bullet.intersects(asteroid)) { bullet.active = false; // Asteroid hit logic if (asteroid.hit()) { // Asteroid destroyed LK.getSound('explosion').play(); // Create explosion effect createExplosion(asteroid.x, asteroid.y); // Update score updateScore(asteroid.value); // Remove asteroid asteroid.active = false; } break; } } } // Check player-asteroid collisions if (!player.invulnerable) { for (var j = asteroids.length - 1; j >= 0; j--) { var asteroid = asteroids[j]; if (!asteroid.active) { continue; } if (player.intersects(asteroid)) { // Player hit if (player.hit()) { // Update lives display livesText.setText("SHIELDS: " + player.lives); // Check game over if (player.lives <= 0) { endGame(); return; } } // Create explosion effect createExplosion(asteroid.x, asteroid.y); // Remove asteroid asteroid.active = false; // Reset combo combo = 0; comboTimer = 0; comboText.alpha = 0; } } } // Check earth-asteroid collisions for (var j = asteroids.length - 1; j >= 0; j--) { var asteroid = asteroids[j]; if (!asteroid.active) { continue; } if (asteroid.intersects(earth)) { // Earth hit var damage = asteroid.size * 5; if (earth.damage(damage)) { // Game over if earth health reaches 0 endGame(); return; } // Update earth health display earthHealthText.setText("EARTH: " + earth.health + "%"); // Create explosion effect createExplosion(asteroid.x, asteroid.y); // Remove asteroid asteroid.active = false; // Reset combo combo = 0; comboTimer = 0; comboText.alpha = 0; } } // Check player-powerup collisions for (var j = powerups.length - 1; j >= 0; j--) { var powerup = powerups[j]; if (!powerup.active) { continue; } if (player.intersects(powerup)) { // Collect powerup LK.getSound('powerup').play(); if (powerup.type === "shield") { player.activateShield(); } else if (powerup.type === "multishot") { player.activateMultishot(); } else if (powerup.type === "bomb") { // Clear all asteroids for (var k = asteroids.length - 1; k >= 0; k--) { var asteroid = asteroids[k]; createExplosion(asteroid.x, asteroid.y); asteroid.active = false; updateScore(asteroid.value / 2); // Half points for bomb kills } // Screen flash LK.effects.flashScreen(0xffff00, 500); } // Remove powerup powerup.active = false; } } } // Create explosion effect function createExplosion(x, y) { var explosion = LK.getAsset('asteroid', { anchorX: 0.5, anchorY: 0.5, x: x, y: y, alpha: 0.8, tint: 0xff9900 }); game.addChild(explosion); // Animate explosion tween(explosion.scale, { x: 3, y: 3 }, { duration: 500, easing: tween.easeOut }); tween(explosion, { alpha: 0 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(explosion); } }); } // Update score with combo multiplier function updateScore(value) { // Update combo combo++; comboTimer = 180; // 3 seconds to maintain combo // Calculate score with combo var multiplier = Math.min(Math.floor(combo / 3) + 1, 5); var points = value * multiplier; score += points; LK.setScore(score); // Update score display scoreTxt.setText("SCORE: " + score); // Show combo text if multiplier > 1 if (multiplier > 1) { comboText.setText("COMBO: x" + multiplier); comboText.alpha = 1; // Make combo text pulse tween.stop(comboText.scale); comboText.scale.set(1); tween(comboText.scale, { x: 1.5, y: 1.5 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(comboText.scale, { x: 1, y: 1 }, { duration: 200, easing: tween.easeIn }); } }); } // Show floating score text var pointText = new Text2("+" + points, { size: 60, fill: 0xFFFF00 }); pointText.anchor.set(0.5, 0.5); pointText.x = player.x; pointText.y = player.y - 100; game.addChild(pointText); // Animate score text tween(pointText, { y: pointText.y - 100, alpha: 0 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(pointText); } }); } // End the game function endGame() { gameOver = true; // Show game over text var gameOverText = new Text2("GAME OVER", { size: 200, fill: 0xFF0000 }); gameOverText.anchor.set(0.5, 0.5); LK.gui.center.addChild(gameOverText); // Animate game over text tween(gameOverText.scale, { x: 1.5, y: 1.5 }, { duration: 1000, easing: tween.easeOut, onFinish: function onFinish() { // Show final score var finalScoreText = new Text2("FINAL SCORE: " + score, { size: 100, fill: 0xFFFFFF }); finalScoreText.anchor.set(0.5, 0.5); finalScoreText.y = 150; LK.gui.center.addChild(finalScoreText); // Show game over after a delay LK.setTimeout(function () { LK.showGameOver(); }, 3000); } }); // Stop music with fade out LK.playMusic('gameMusic', { fade: { start: 0.3, end: 0, duration: 2000 } }); } // Handle drag movement for player ship function handleMove(x, y, obj) { if (dragMode && gameStarted && !gameOver) { player.x = x; // Keep player within bounds if (player.x < 75) { player.x = 75; } if (player.x > GAME_WIDTH - 75) { player.x = GAME_WIDTH - 75; } } } // Initialize game initGame(); // Game mouse/touch events game.down = function (x, y, obj) { if (!gameStarted) { startGame(); return; } if (gameOver) { return; } dragMode = true; player.x = x; // Keep player within bounds if (player.x < 75) { player.x = 75; } if (player.x > GAME_WIDTH - 75) { player.x = GAME_WIDTH - 75; } // Fire bullet on touch fireBullet(); }; game.up = function (x, y, obj) { dragMode = false; }; game.move = handleMove; // Game update loop game.update = function () { if (!gameStarted) { return; } if (gameOver) { return; } // Update player player.update(); // Fire automatically every 15 frames (4 times per second) if (LK.ticks % 15 === 0) { fireBullet(); } // Update combo timer if (combo > 0) { comboTimer--; if (comboTimer <= 0) { combo = 0; tween(comboText, { alpha: 0 }, { duration: 500, easing: tween.easeOut }); } } // Update wave delay if (waveDelay > 0) { waveDelay--; if (waveDelay <= 0) { spawnWave(); waveDelay = WAVE_DELAY; } } // Random asteroid spawn between waves (with increasing chance based on wave) if (asteroids.length < MAX_ASTEROIDS && Math.random() < ASTEROID_SPAWN_CHANCE * (1 + waveNumber * 0.1)) { spawnAsteroid(); } // Random powerup spawn if (Math.random() < POWERUP_CHANCE) { spawnPowerup(); } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].update(); if (!bullets[i].active) { game.removeChild(bullets[i]); bullets.splice(i, 1); } } // Update asteroids for (var i = asteroids.length - 1; i >= 0; i--) { asteroids[i].update(); if (!asteroids[i].active) { game.removeChild(asteroids[i]); asteroids.splice(i, 1); } } // Update powerups for (var i = powerups.length - 1; i >= 0; i--) { powerups[i].update(); if (!powerups[i].active) { game.removeChild(powerups[i]); powerups.splice(i, 1); } } // Check collisions checkCollisions(); };
===================================================================
--- original.js
+++ change.js
@@ -431,9 +431,9 @@
function spawnAsteroid(size, speed) {
var asteroid = new Asteroid();
asteroid.x = Math.random() * (GAME_WIDTH - 100) + 50;
asteroid.y = -100;
- asteroid.speed = speed || 2;
+ asteroid.speed = Math.min(speed || 2, 2);
asteroid.setup(size || 1);
asteroids.push(asteroid);
game.addChild(asteroid);
return asteroid;
Earth. 2d
Asteroid. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Spaceship. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Space ship plasma bullet. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows