/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { credits: 0, laserLevel: 1, shieldLevel: 1, engineLevel: 1, highScore: 0 }); /**** * Classes ****/ var Alien = Container.expand(function () { var self = Container.call(this); self.health = 75; self.size = 'alien'; self.value = 15; // Create pixel art alien ship // Main body - larger central pixel var alienGraphics = self.attachAsset('asteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.5, tint: 0x9933ff // Purple alien ship }); // Create alien ship details with smaller blocks // Top section var topSection = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.2, tint: 0xcc66ff // Lighter purple }); topSection.y = -20; self.addChild(topSection); // Bottom section var bottomSection = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.2, tint: 0xcc66ff // Lighter purple }); bottomSection.y = 20; self.addChild(bottomSection); // Left wing var leftWing = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, tint: 0x6600cc // Darker purple }); leftWing.x = -30; self.addChild(leftWing); // Right wing var rightWing = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, tint: 0x6600cc // Darker purple }); rightWing.x = 30; self.addChild(rightWing); // Cockpit glow - central pixel var cockpit = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, tint: 0xff33cc // Pink glow }); cockpit.y = -5; self.addChild(cockpit); // Random movement pattern self.vx = Math.random() * 4 - 2; self.vy = Math.random() * 2 + 1; self.fireTimer = Math.floor(Math.random() * 60); self.targetX = 0; self.targetY = 0; self.update = function () { // Move in a slight sine wave pattern self.x += self.vx + Math.sin(LK.ticks / 20) * 1.5; self.y += self.vy; // Occasionally change horizontal direction if (LK.ticks % 120 === 0) { self.vx = Math.random() * 4 - 2; } // Wrap around screen edges horizontally if (self.x < -60) { self.x = 2108; } if (self.x > 2108) { self.x = -60; } // Target the ship if it exists if (ship) { self.targetX = ship.x; self.targetY = ship.y; } // Fire timer for shooting at player self.fireTimer++; }; self.takeDamage = function (amount) { self.health -= amount; // Visual feedback tween(alienGraphics, { tint: 0xff8800 }, { duration: 100, onFinish: function onFinish() { tween(alienGraphics, { tint: 0x2ecc71 }, { duration: 200 }); } }); return self.health <= 0; }; self.split = function () { var fragments = []; // Create resources for (var i = 0; i < self.value; i++) { var resource = new Resource(); resource.x = self.x + (Math.random() * 60 - 30); resource.y = self.y + (Math.random() * 60 - 30); resource.vx = Math.random() * 4 - 2; resource.vy = Math.random() * 4 - 2 + self.vy; fragments.push(resource); } return fragments; }; return self; }); var AlienLaser = Container.expand(function () { var self = Container.call(this); // Main pixel for alien laser var laserGraphics = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 1.0, tint: 0xff3366 // Pink-red alien laser }); // Add pixel art detail - laser head var laserHead = LK.getAsset('laser', { anchorX: 0.5, anchorY: 0.0, scaleX: 1.0, scaleY: 0.3, tint: 0xff99aa // Lighter pinkish }); self.addChild(laserHead); // Add pixel art detail - laser trail var laserTrail = LK.getAsset('laser', { anchorX: 0.5, anchorY: 1.0, scaleX: 0.5, scaleY: 0.4, tint: 0xcc0033 // Darker red }); laserTrail.y = 15; self.addChild(laserTrail); self.speed = 10; self.power = 15; self.targetX = 0; self.targetY = 0; self.vx = 0; self.vy = 0; self.setup = function (startX, startY, targetX, targetY) { self.x = startX; self.y = startY; // Calculate direction toward target var dx = targetX - startX; var dy = targetY - startY; var dist = Math.sqrt(dx * dx + dy * dy); // Normalize and apply speed if (dist > 0) { self.vx = dx / dist * self.speed; self.vy = dy / dist * self.speed; } else { self.vy = self.speed; } // Rotate laser to point in direction of movement self.rotation = Math.atan2(dy, dx) + Math.PI / 2; }; self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); var Asteroid = Container.expand(function () { var self = Container.call(this); self.size = 'large'; self.value = Math.floor(Math.random() * 5) + 5; self.health = 100; // Create a pixel art asteroid by composing multiple blocks var asteroidCore = self.attachAsset('asteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8, tint: 0x888888 // Base gray color }); // Add pixel blocks for asteroid jagged edges var asteroidParts = []; var numParts = 8; // Number of pixel blocks to add for (var i = 0; i < numParts; i++) { var angle = i / numParts * Math.PI * 2; var distance = 30 + Math.random() * 20; // Vary distance from center var size = 0.2 + Math.random() * 0.3; // Vary block size // Slightly varied gray tones for pixel art effect var tint = 0x666666 + Math.floor(Math.random() * 0x333333); var part = LK.getAsset('asteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: size, scaleY: size, tint: tint }); part.x = Math.cos(angle) * distance; part.y = Math.sin(angle) * distance; self.addChild(part); asteroidParts.push(part); } // Random rotation speed self.rotationSpeed = Math.random() * 0.02 - 0.01; // Random velocity self.vx = Math.random() * 2 - 1; self.vy = Math.random() * 3 + 1; self.update = function () { self.rotation += self.rotationSpeed; self.x += self.vx; self.y += self.vy; // Wrap around screen edges horizontally if (self.x < -100) { self.x = 2148; } if (self.x > 2148) { self.x = -100; } }; self.takeDamage = function (amount) { self.health -= amount; // Visual feedback tween(asteroidCore, { tint: 0xff8800 }, { duration: 100, onFinish: function onFinish() { tween(asteroidCore, { tint: 0x888888 }, { duration: 200 }); } }); return self.health <= 0; }; self.split = function () { var fragments = []; if (self.size === 'large') { // Create 2 smaller asteroids for (var i = 0; i < 2; i++) { var smallAsteroid = new SmallAsteroid(); smallAsteroid.x = self.x + (Math.random() * 40 - 20); smallAsteroid.y = self.y + (Math.random() * 40 - 20); smallAsteroid.vx = self.vx + (Math.random() * 2 - 1); smallAsteroid.vy = self.vy + (Math.random() * 2 - 1); fragments.push(smallAsteroid); } // Create resources for (var j = 0; j < self.value; j++) { var resource = new Resource(); resource.x = self.x + (Math.random() * 60 - 30); resource.y = self.y + (Math.random() * 60 - 30); resource.vx = Math.random() * 4 - 2; resource.vy = Math.random() * 4 - 2 + self.vy; fragments.push(resource); } } return fragments; }; return self; }); var Laser = Container.expand(function () { var self = Container.call(this); // Main laser beam var laserGraphics = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 1.2, tint: 0x22ff44 // Bright green laser }); // Add pixel art details to laser - head glow var laserHead = LK.getAsset('laser', { anchorX: 0.5, anchorY: 0.0, scaleX: 1.2, scaleY: 0.3, tint: 0x88ffaa // Lighter green for head }); laserHead.y = -15; self.addChild(laserHead); // Add pixel art details to laser - tail var laserTail = LK.getAsset('laser', { anchorX: 0.5, anchorY: 1.0, scaleX: 0.6, scaleY: 0.4, tint: 0x118822 // Darker green for tail }); laserTail.y = 15; self.addChild(laserTail); self.speed = -15; self.power = 25; self.update = function () { self.y += self.speed; }; return self; }); var Map = Container.expand(function () { var self = Container.call(this); // Create map background var mapBg = self.attachAsset('radarBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0x1a2733, alpha: 0.7 }); // Create player position indicator var playerMarker = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5, tint: 0x4286f4 // Blue to match player ship }); self.addChild(playerMarker); // Create array to hold map markers self.markers = []; // Update map with game objects self.updateMap = function (playerPos, gameObjects) { // Position player marker at center playerMarker.x = 0; playerMarker.y = 0; // Clear existing markers for (var i = 0; i < self.markers.length; i++) { self.removeChild(self.markers[i]); } self.markers = []; // Map dimensions var mapWidth = mapBg.width; var mapHeight = mapBg.height; // Add markers for game objects for (var i = 0; i < gameObjects.length; i++) { var obj = gameObjects[i]; // Calculate relative position var relX = (obj.x - playerPos.x) / 800; // Scale down game world var relY = (obj.y - playerPos.y) / 800; // If within map bounds if (Math.abs(relX) < mapWidth / 2 && Math.abs(relY) < mapHeight / 2) { var marker = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3 }); // Set position marker.x = relX; marker.y = relY; // Set color based on object type if (obj.size === 'large') { marker.tint = 0x7f8c8d; // Gray for asteroids } else if (obj.size === 'small') { marker.tint = 0x95a5a6; // Light gray for small asteroids } else if (obj.size === 'alien') { marker.tint = 0xff0000; // Red for aliens } else { marker.tint = 0xf1c40f; // Yellow for resources } self.addChild(marker); self.markers.push(marker); } } }; return self; }); var MiningShip = Container.expand(function () { var self = Container.call(this); // Create main pixel art spaceship container var shipContainer = new Container(); self.addChild(shipContainer); // Create ship body (main part) - center pixel block var shipBody = self.attachAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.6, tint: 0x4286f4 // Main ship color }); // Create ship nose - front pixel block var shipNose = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.3, tint: 0x4286f4 }); shipNose.y = -30; self.addChild(shipNose); // Create left wing - pixel blocks var leftWing = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, tint: 0x2255cc // Wing color }); leftWing.x = -40; leftWing.y = 0; self.addChild(leftWing); // Wing tip var leftWingTip = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, tint: 0x2255cc }); leftWingTip.x = -60; leftWingTip.y = 10; self.addChild(leftWingTip); // Create right wing - pixel blocks var rightWing = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.4, scaleY: 0.4, tint: 0x2255cc // Wing color }); rightWing.x = 40; rightWing.y = 0; self.addChild(rightWing); // Wing tip var rightWingTip = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, tint: 0x2255cc }); rightWingTip.x = 60; rightWingTip.y = 10; self.addChild(rightWingTip); // Cockpit - center pixel var cockpit = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.2, tint: 0x22ffdd // Cockpit color }); cockpit.y = -15; self.addChild(cockpit); // Engine exhausts - pixelated thruster flames var leftExhaust = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, tint: 0xff6600 // Orange exhaust }); leftExhaust.x = -20; leftExhaust.y = 30; self.addChild(leftExhaust); var rightExhaust = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3, tint: 0xff6600 // Orange exhaust }); rightExhaust.x = 20; rightExhaust.y = 30; self.addChild(rightExhaust); // Small exhaust flames for pixel art effect var leftExhaustTip = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, tint: 0xffcc00 // Yellow exhaust tip }); leftExhaustTip.x = -20; leftExhaustTip.y = 38; self.addChild(leftExhaustTip); var rightExhaustTip = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2, scaleY: 0.2, tint: 0xffcc00 // Yellow exhaust tip }); rightExhaustTip.x = 20; rightExhaustTip.y = 38; self.addChild(rightExhaustTip); // Animate engine exhausts function animateExhausts() { // Animate main exhausts tween(leftExhaust, { scaleY: 0.4, alpha: 0.8 }, { duration: 400, onFinish: function onFinish() { tween(leftExhaust, { scaleY: 0.3, alpha: 1.0 }, { duration: 400, onFinish: animateExhausts }); } }); tween(rightExhaust, { scaleY: 0.4, alpha: 0.8 }, { duration: 400, easing: tween.easeOut }); // Animate exhaust tips for pixel art flame effect tween(leftExhaustTip, { scaleY: 0.3, alpha: 0.9 }, { duration: 200, easing: tween.easeOut }); tween(rightExhaustTip, { scaleY: 0.3, alpha: 0.9 }, { duration: 200, easing: tween.easeOut }); } animateExhausts(); var shieldGraphics = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0.3 }); self.health = 100; self.maxHealth = 100; self.speed = 5; self.laserPower = storage.laserLevel; self.shieldStrength = storage.shieldLevel; // Increase speed based on engine level self.speed += storage.engineLevel; // Make shield size based on shield level shieldGraphics.scale.set(1 + storage.shieldLevel * 0.1); self.activateShield = function () { if (self.shield > 0) { tween(shieldGraphics, { alpha: 0.5 }, { duration: 200, onFinish: function onFinish() { tween(shieldGraphics, { alpha: 0.3 }, { duration: 800 }); } }); } }; self.takeDamage = function (amount) { var actualDamage = amount / self.shieldStrength; self.health -= actualDamage; if (self.health <= 0) { self.health = 0; } // Flash red to indicate damage LK.getSound('shipDamage').play(); tween(shipBody, { tint: 0xff0000 }, { duration: 100, onFinish: function onFinish() { tween(shipBody, { tint: 0x4286f4 // Return to original blue color }, { duration: 200 }); } }); // Activate shield effect self.activateShield(); return self.health <= 0; }; return self; }); var Radar = Container.expand(function () { var self = Container.call(this); var background = self.attachAsset('radarBackground', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); self.blips = []; self.updateRadar = function (asteroids) { // Clear existing blips for (var i = 0; i < self.blips.length; i++) { self.removeChild(self.blips[i]); } self.blips = []; // Add new blips for asteroids for (var j = 0; j < asteroids.length; j++) { var asteroid = asteroids[j]; // Only show blips for asteroids that are off-screen or about to enter if (asteroid.y < -100) { var blip = LK.getAsset('radarBlip', { anchorX: 0.5, anchorY: 0.5 }); // Scale radar coordinates to fit in radar display var radarX = asteroid.x / 2048 * background.width - background.width / 2; var radarY = (asteroid.y + 300) / 800 * background.height - background.height / 2; // Clamp to radar boundaries radarY = Math.max(-background.height / 2, Math.min(radarY, background.height / 2)); radarX = Math.max(-background.width / 2, Math.min(radarX, background.width / 2)); blip.x = radarX; blip.y = radarY; // Size and color based on object type if (asteroid.size === 'large') { blip.scale.set(1.5); } // If it's an alien, make the blip red if (asteroid.size === 'alien') { blip.tint = 0xff0000; blip.scale.set(1.2); } self.addChild(blip); self.blips.push(blip); } } }; return self; }); var Resource = Container.expand(function () { var self = Container.call(this); // Create main pixel for resource var resourceGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); self.value = Math.floor(Math.random() * 5) + 1; self.collected = false; // Set random value-based tint - higher value = more golden var colorValue = Math.min(0xFFFFFF, 0xC0C0C0 + self.value * 0x101000); resourceGraphics.tint = colorValue; // Create smaller pixels around central pixel for gem-like appearance var pixelSize = 0.3; var pixelDistance = 8; // Add 4 smaller pixels in a + pattern around the main resource for (var i = 0; i < 4; i++) { var angle = i / 4 * Math.PI * 2; var pixelX = Math.cos(angle) * pixelDistance; var pixelY = Math.sin(angle) * pixelDistance; var pixel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: pixelSize, scaleY: pixelSize, tint: 0xFFFFFF // Brighter to create highlight effect }); pixel.x = pixelX; pixel.y = pixelY; pixel.alpha = 0.8; self.addChild(pixel); } // Random velocity self.vx = 0; self.vy = 0; self.update = function () { self.x += self.vx; self.y += self.vy; // Gradually slow down self.vx *= 0.98; self.vy *= 0.98; // Resource magnetized to ship when close enough if (ship && !self.collected) { var dx = ship.x - self.x; var dy = ship.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 200) { // Apply force proportional to distance var strength = (1 - distance / 200) * 0.5; self.vx += dx * strength; self.vy += dy * strength; } } }; self.collect = function () { if (!self.collected) { self.collected = true; // Animation for collection tween(self, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, easing: tween.easeOut }); return self.value; } return 0; }; return self; }); var SmallAsteroid = Container.expand(function () { var self = Container.call(this); self.size = 'small'; self.value = Math.floor(Math.random() * 3) + 1; self.health = 50; // Create a pixel art small asteroid core var asteroidGraphics = self.attachAsset('smallAsteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.6, tint: 0x777777 }); // Add smaller pixel blocks for jagged edges var numParts = 5; // Fewer parts for smaller asteroid for (var i = 0; i < numParts; i++) { var angle = i / numParts * Math.PI * 2; var distance = 15 + Math.random() * 10; // Smaller distance var size = 0.15 + Math.random() * 0.2; // Smaller blocks // Slightly varied gray tones var tint = 0x666666 + Math.floor(Math.random() * 0x222222); var part = LK.getAsset('smallAsteroid', { anchorX: 0.5, anchorY: 0.5, scaleX: size, scaleY: size, tint: tint }); part.x = Math.cos(angle) * distance; part.y = Math.sin(angle) * distance; self.addChild(part); } // Random rotation speed self.rotationSpeed = Math.random() * 0.04 - 0.02; // Random velocity self.vx = Math.random() * 3 - 1.5; self.vy = Math.random() * 3 + 2; self.update = function () { self.rotation += self.rotationSpeed; self.x += self.vx; self.y += self.vy; // Wrap around screen edges horizontally if (self.x < -50) { self.x = 2098; } if (self.x > 2098) { self.x = -50; } }; self.takeDamage = function (amount) { self.health -= amount; // Visual feedback tween(asteroidGraphics, { tint: 0xff8800 }, { duration: 100, onFinish: function onFinish() { tween(asteroidGraphics, { tint: 0x777777 }, { duration: 200 }); } }); return self.health <= 0; }; self.split = function () { var fragments = []; // Create resources for (var i = 0; i < self.value; i++) { var resource = new Resource(); resource.x = self.x + (Math.random() * 30 - 15); resource.y = self.y + (Math.random() * 30 - 15); resource.vx = Math.random() * 3 - 1.5; resource.vy = Math.random() * 3 - 1.5 + self.vy; fragments.push(resource); } return fragments; }; return self; }); var Star = Container.expand(function () { var self = Container.call(this); // Create a pixel art star var starSize = 0.1 + Math.random() * 0.4; // Vary star sizes var brightness = 0.5 + Math.random() * 0.5; // Vary star brightness // Create the star shape (using a small resource asset for the star point) var starGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: starSize, scaleY: starSize, tint: 0xFFFFFF // White star }); starGraphics.alpha = brightness; // Star twinkle effect function twinkle() { // Random twinkle duration var duration = 1000 + Math.random() * 2000; // Random target alpha for twinkling var targetAlpha = 0.2 + Math.random() * 0.8; tween(starGraphics, { alpha: targetAlpha }, { duration: duration, onFinish: twinkle }); } // Start twinkling with a random delay LK.setTimeout(twinkle, Math.random() * 3000); // Parallax scrolling speed (deeper stars move slower) self.scrollSpeed = 0.1 + Math.random() * 0.4; self.update = function () { // Move star down very slowly (parallax effect) self.y += self.scrollSpeed; // Wrap around when it goes off screen if (self.y > 2732) { self.y = -10; self.x = Math.random() * 2048; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) { return _arrayLikeToArray(r, a); } var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) { return Array.from(r); } } function _arrayWithoutHoles(r) { if (Array.isArray(r)) { return _arrayLikeToArray(r); } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) { n[e] = r[e]; } return n; } game.setBackgroundColor(0x0A0A2A); // Deep space blue // Game state variables var ship; var lasers = []; var asteroids = []; var resources = []; var aliens = []; var alienLasers = []; var stars = []; // Array to hold background stars var map; // Map object for HUD var gameLevel = 1; var spawnTimer = 0; var spawnInterval = 120; // Frames between asteroid spawns var alienSpawnTimer = 0; var alienSpawnInterval = 600; // Frames between alien spawns var levelTimer = 0; var levelDuration = 1800; // 30 seconds at 60fps var score = 0; var credits = storage.credits || 0; var levelUpPopupVisible = false; // UI elements var scoreTxt = new Text2('Score: 0', { size: 30, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -200; scoreTxt.y = 20; var creditsTxt = new Text2('Credits: ' + credits, { size: 30, fill: 0xFFDD00 }); creditsTxt.anchor.set(0, 0); LK.gui.topRight.addChild(creditsTxt); creditsTxt.x = -200; creditsTxt.y = 60; var levelTxt = new Text2('Level: ' + gameLevel, { size: 30, fill: 0xFFFFFF }); levelTxt.anchor.set(0, 0); LK.gui.topRight.addChild(levelTxt); levelTxt.x = -200; levelTxt.y = 100; var healthBar = new Container(); var healthBarBg = LK.getAsset('miningShip', { anchorX: 0, anchorY: 0.5, scaleX: 2, scaleY: 0.3, tint: 0x444444 }); var healthBarFill = LK.getAsset('miningShip', { anchorX: 0, anchorY: 0.5, scaleX: 2, scaleY: 0.25, tint: 0x00FF00 }); healthBar.addChild(healthBarBg); healthBar.addChild(healthBarFill); healthBar.x = 120; healthBar.y = 30; LK.gui.topLeft.addChild(healthBar); // Upgrade UI section (initially hidden) var upgradeContainer = new Container(); upgradeContainer.visible = false; LK.gui.center.addChild(upgradeContainer); var upgradePanel = LK.getAsset('radarBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2.5, tint: 0x223344 }); upgradeContainer.addChild(upgradePanel); var upgradeTitle = new Text2('UPGRADE SHIP', { size: 50, fill: 0xFFFFFF }); upgradeTitle.anchor.set(0.5, 0); upgradeTitle.y = -200; upgradeContainer.addChild(upgradeTitle); var laserUpgradeBtn = new Container(); laserUpgradeBtn.y = -100; upgradeContainer.addChild(laserUpgradeBtn); var laserBtnBg = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 0.6, tint: 0x2ecc71 }); laserUpgradeBtn.addChild(laserBtnBg); var laserBtnTxt = new Text2('Laser Lvl ' + storage.laserLevel + ' → ' + (storage.laserLevel + 1) + ' (Cost: 100)', { size: 25, fill: 0xFFFFFF }); laserBtnTxt.anchor.set(0.5, 0.5); laserUpgradeBtn.addChild(laserBtnTxt); var shieldUpgradeBtn = new Container(); shieldUpgradeBtn.y = 0; upgradeContainer.addChild(shieldUpgradeBtn); var shieldBtnBg = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 0.6, tint: 0x3498db }); shieldUpgradeBtn.addChild(shieldBtnBg); var shieldBtnTxt = new Text2('Shield Lvl ' + storage.shieldLevel + ' → ' + (storage.shieldLevel + 1) + ' (Cost: 150)', { size: 25, fill: 0xFFFFFF }); shieldBtnTxt.anchor.set(0.5, 0.5); shieldUpgradeBtn.addChild(shieldBtnTxt); var engineUpgradeBtn = new Container(); engineUpgradeBtn.y = 100; upgradeContainer.addChild(engineUpgradeBtn); var engineBtnBg = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 0.6, tint: 0xf39c12 }); engineUpgradeBtn.addChild(engineBtnBg); var engineBtnTxt = new Text2('Engine Lvl ' + storage.engineLevel + ' → ' + (storage.engineLevel + 1) + ' (Cost: 125)', { size: 25, fill: 0xFFFFFF }); engineBtnTxt.anchor.set(0.5, 0.5); engineUpgradeBtn.addChild(engineBtnTxt); var continueBtn = new Container(); continueBtn.y = 200; upgradeContainer.addChild(continueBtn); var continueBtnBg = LK.getAsset('miningShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 0.6, tint: 0xe74c3c }); continueBtn.addChild(continueBtnBg); var continueBtnTxt = new Text2('CONTINUE MINING', { size: 30, fill: 0xFFFFFF }); continueBtnTxt.anchor.set(0.5, 0.5); continueBtn.addChild(continueBtnTxt); // Radar system at bottom var radar = new Radar(); radar.x = 2048 / 2; radar.y = 2732 - 120; game.addChild(radar); // Initialize the ship function initShip() { ship = new MiningShip(); ship.x = 2048 / 2; ship.y = 2732 - 400; game.addChild(ship); } // Initialize stars for the background function initStars() { // Create a good number of stars for the background var numStars = 150; // Clear any existing stars first for (var i = 0; i < stars.length; i++) { if (stars[i].parent) { stars[i].parent.removeChild(stars[i]); } } stars = []; // Create and position new stars for (var i = 0; i < numStars; i++) { var star = new Star(); // Position randomly across the entire screen star.x = Math.random() * 2048; star.y = Math.random() * 2732; // Add to game (behind other elements) game.addChildAt(star, 0); stars.push(star); } } // Initialize game function initGame() { // Start with a clean slate clearGameElements(); // Load credits from storage credits = storage.credits || 0; // Initialize stars for background initStars(); // Initialize ship initShip(); // Reset game state gameLevel = 1; score = 0; spawnTimer = 0; alienSpawnTimer = 0; levelTimer = 0; levelUpPopupVisible = false; // Initialize map if (map && map.parent) { map.parent.removeChild(map); } map = new Map(); map.x = 120; map.y = 180; LK.gui.topLeft.addChild(map); // Update UI updateUI(); // Start background music LK.playMusic('spaceAmbience'); } // Clear all game elements function clearGameElements() { // Remove all asteroids for (var i = 0; i < asteroids.length; i++) { if (asteroids[i].parent) { asteroids[i].parent.removeChild(asteroids[i]); } } asteroids = []; // Remove all lasers for (var j = 0; j < lasers.length; j++) { if (lasers[j].parent) { lasers[j].parent.removeChild(lasers[j]); } } lasers = []; // Remove all resources for (var k = 0; k < resources.length; k++) { if (resources[k].parent) { resources[k].parent.removeChild(resources[k]); } } resources = []; // Remove all aliens for (var a = 0; a < aliens.length; a++) { if (aliens[a].parent) { aliens[a].parent.removeChild(aliens[a]); } } aliens = []; // Remove all alien lasers for (var al = 0; al < alienLasers.length; al++) { if (alienLasers[al].parent) { alienLasers[al].parent.removeChild(alienLasers[al]); } } alienLasers = []; // Remove all stars for (var s = 0; s < stars.length; s++) { if (stars[s].parent) { stars[s].parent.removeChild(stars[s]); } } stars = []; // Remove ship if it exists if (ship && ship.parent) { ship.parent.removeChild(ship); } // Hide upgrade panel upgradeContainer.visible = false; // Remove map if it exists if (map && map.parent) { map.parent.removeChild(map); } } // Update UI elements function updateUI() { scoreTxt.setText('Score: ' + score); creditsTxt.setText('Credits: ' + credits); levelTxt.setText('Level: ' + gameLevel); // Update health bar if (ship) { healthBarFill.scale.x = 2 * (ship.health / ship.maxHealth); // Change color based on health if (ship.health > 70) { healthBarFill.tint = 0x00FF00; } else if (ship.health > 30) { healthBarFill.tint = 0xFFAA00; } else { healthBarFill.tint = 0xFF0000; } } // Update upgrade buttons laserBtnTxt.setText('Laser Lvl ' + storage.laserLevel + ' → ' + (storage.laserLevel + 1) + ' (Cost: 100)'); shieldBtnTxt.setText('Shield Lvl ' + storage.shieldLevel + ' → ' + (storage.shieldLevel + 1) + ' (Cost: 150)'); engineBtnTxt.setText('Engine Lvl ' + storage.engineLevel + ' → ' + (storage.engineLevel + 1) + ' (Cost: 125)'); } // Spawn an asteroid function spawnAsteroid() { var asteroid = new Asteroid(); asteroid.x = Math.random() * 2048; asteroid.y = -200; // Adjust velocity based on level asteroid.vy = 1 + gameLevel * 0.5; if (gameLevel > 5) { // More horizontal movement in higher levels asteroid.vx = (Math.random() * 3 - 1.5) * (gameLevel * 0.2); } asteroids.push(asteroid); game.addChild(asteroid); } // Spawn an alien ship function spawnAlien() { var alien = new Alien(); alien.x = Math.random() * 2048; alien.y = -200; // Adjust velocity based on level alien.vy = 0.8 + gameLevel * 0.3; aliens.push(alien); game.addChild(alien); } // Alien fires a laser at the player function fireAlienLaser(alien) { var laser = new AlienLaser(); laser.setup(alien.x, alien.y, alien.targetX, alien.targetY); alienLasers.push(laser); game.addChild(laser); } // Fire a laser from the ship function fireLaser() { var laser = new Laser(); laser.x = ship.x; laser.y = ship.y - 40; laser.power = 25 * ship.laserPower; lasers.push(laser); game.addChild(laser); LK.getSound('laserSound').play(); } // Show upgrade UI between levels function showUpgradeUI() { upgradeContainer.visible = true; levelUpPopupVisible = true; // Update button texts laserBtnTxt.setText('Laser Lvl ' + storage.laserLevel + ' → ' + (storage.laserLevel + 1) + ' (Cost: 100)'); shieldBtnTxt.setText('Shield Lvl ' + storage.shieldLevel + ' → ' + (storage.shieldLevel + 1) + ' (Cost: 150)'); engineBtnTxt.setText('Engine Lvl ' + storage.engineLevel + ' → ' + (storage.engineLevel + 1) + ' (Cost: 125)'); // Update button colors based on affordability laserBtnBg.tint = credits >= 100 ? 0x2ecc71 : 0x95a5a6; shieldBtnBg.tint = credits >= 150 ? 0x3498db : 0x95a5a6; engineBtnBg.tint = credits >= 125 ? 0xf39c12 : 0x95a5a6; } // Hide upgrade UI function hideUpgradeUI() { upgradeContainer.visible = false; levelUpPopupVisible = false; // Reinitialize ship with new upgrades if (ship && ship.parent) { ship.parent.removeChild(ship); } initShip(); } // Handle upgrade button clicks function handleUpgradeClick(x, y) { if (!levelUpPopupVisible) { return; } // Convert global coordinates to local coordinates for the upgrade container var local = upgradeContainer.toLocal({ x: x, y: y }); // Check if laser upgrade button was clicked if (local.y > -130 && local.y < -70 && local.x > -150 && local.x < 150 && credits >= 100) { // Upgrade laser credits -= 100; storage.laserLevel += 1; storage.credits = credits; updateUI(); // Visual feedback tween(laserUpgradeBtn, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(laserUpgradeBtn, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } // Check if shield upgrade button was clicked else if (local.y > -30 && local.y < 30 && local.x > -150 && local.x < 150 && credits >= 150) { // Upgrade shield credits -= 150; storage.shieldLevel += 1; storage.credits = credits; updateUI(); // Visual feedback tween(shieldUpgradeBtn, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(shieldUpgradeBtn, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } // Check if engine upgrade button was clicked else if (local.y > 70 && local.y < 130 && local.x > -150 && local.x < 150 && credits >= 125) { // Upgrade engine credits -= 125; storage.engineLevel += 1; storage.credits = credits; updateUI(); // Visual feedback tween(engineUpgradeBtn, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(engineUpgradeBtn, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } // Check if continue button was clicked else if (local.y > 170 && local.y < 230 && local.x > -150 && local.x < 150) { // Continue to next level hideUpgradeUI(); // Visual feedback tween(continueBtn, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(continueBtn, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } } // Mouse/touch events var dragMode = false; var lastX = 0; game.down = function (x, y, obj) { // Handle upgrade UI clicks if visible if (levelUpPopupVisible) { handleUpgradeClick(x, y); return; } // Start tracking for ship movement dragMode = true; lastX = x; // Fire laser when tapping/clicking if (ship && !levelUpPopupVisible) { fireLaser(); } }; game.up = function (x, y, obj) { dragMode = false; }; game.move = function (x, y, obj) { if (dragMode && ship && !levelUpPopupVisible) { // Move ship based on drag distance var dx = x - lastX; ship.x += dx * 1.5; // Constrain to screen ship.x = Math.max(50, Math.min(ship.x, 2048 - 50)); lastX = x; } }; // Game logic update game.update = function () { if (levelUpPopupVisible) { // Only handle UI events when upgrade screen is visible return; } // Spawning logic spawnTimer++; if (spawnTimer >= spawnInterval) { spawnTimer = 0; spawnAsteroid(); // Adjust spawn rate based on level spawnInterval = Math.max(30, 120 - gameLevel * 10); } // Alien spawning logic alienSpawnTimer++; if (alienSpawnTimer >= alienSpawnInterval && gameLevel >= 2) { alienSpawnTimer = 0; spawnAlien(); // Adjust spawn rate based on level alienSpawnInterval = Math.max(300, 600 - gameLevel * 50); } // Level progression levelTimer++; if (levelTimer >= levelDuration) { levelTimer = 0; gameLevel++; levelTxt.setText('Level: ' + gameLevel); // Show upgrade UI between levels showUpgradeUI(); // Save progress storage.credits = credits; } // Update ship if it exists if (ship) { // Constrain to screen ship.x = Math.max(50, Math.min(ship.x, 2048 - 50)); } // Update lasers for (var i = lasers.length - 1; i >= 0; i--) { var laser = lasers[i]; laser.update(); // Remove lasers that go off screen if (laser.y < -50) { game.removeChild(laser); lasers.splice(i, 1); continue; } // Check for collision with asteroids for (var j = asteroids.length - 1; j >= 0; j--) { var asteroid = asteroids[j]; if (laser.intersects(asteroid)) { // Apply damage to asteroid var destroyed = asteroid.takeDamage(laser.power); if (destroyed) { // Break asteroid LK.getSound('asteroidBreak').play(); // Get fragments (smaller asteroids and resources) var fragments = asteroid.split(); // Add fragments to the game for (var k = 0; k < fragments.length; k++) { var fragment = fragments[k]; if (fragment instanceof SmallAsteroid) { asteroids.push(fragment); game.addChild(fragment); } else if (fragment instanceof Resource) { resources.push(fragment); game.addChild(fragment); } } // Remove the destroyed asteroid game.removeChild(asteroid); asteroids.splice(j, 1); // Add to score score += 10; scoreTxt.setText('Score: ' + score); } // Remove the laser that hit game.removeChild(laser); lasers.splice(i, 1); break; } } // Check for collision with aliens for (var a = aliens.length - 1; a >= 0; a--) { var alien = aliens[a]; if (laser.intersects(alien)) { // Apply damage to alien var alienDestroyed = alien.takeDamage(laser.power); if (alienDestroyed) { // Get resources from destroyed alien var alienFragments = alien.split(); // Add fragments to the game for (var af = 0; af < alienFragments.length; af++) { var alienFragment = alienFragments[af]; if (alienFragment instanceof Resource) { resources.push(alienFragment); game.addChild(alienFragment); } } // Remove the destroyed alien game.removeChild(alien); aliens.splice(a, 1); // Add to score score += 25; scoreTxt.setText('Score: ' + score); } // Remove the laser that hit game.removeChild(laser); lasers.splice(i, 1); break; } } } // Update aliens for (var al = aliens.length - 1; al >= 0; al--) { var alien = aliens[al]; alien.update(); // Remove aliens that go off screen if (alien.y > 2832) { game.removeChild(alien); aliens.splice(al, 1); continue; } // Occasionally fire at player if in range if (alien.fireTimer >= 120 && ship) { // Reset fire timer alien.fireTimer = 0; // Only fire if within reasonable range var dx = Math.abs(ship.x - alien.x); if (dx < 500) { fireAlienLaser(alien); } } // Check collision with ship if (ship && alien.intersects(ship)) { // Ship takes damage from alien collision var alienDamage = 30; var gameOver = ship.takeDamage(alienDamage); if (gameOver) { // Check if a new high score was achieved if (score > storage.highScore) { storage.highScore = score; } // Save credits earned storage.credits = credits; // Show game over screen LK.showGameOver(); return; } // Remove alien that hit the ship game.removeChild(alien); aliens.splice(al, 1); // Flash screen to indicate damage LK.effects.flashScreen(0xFF0000, 300); continue; } } // Update alien lasers for (var al = alienLasers.length - 1; al >= 0; al--) { var alienLaser = alienLasers[al]; alienLaser.update(); // Remove alien lasers that go off screen if (alienLaser.y > 2832 || alienLaser.y < -50 || alienLaser.x < -50 || alienLaser.x > 2098) { game.removeChild(alienLaser); alienLasers.splice(al, 1); continue; } // Check collision with ship if (ship && alienLaser.intersects(ship)) { // Ship takes damage from alien laser var laserDamage = 20; var gameOver = ship.takeDamage(laserDamage); if (gameOver) { // Check if a new high score was achieved if (score > storage.highScore) { storage.highScore = score; } // Save credits earned storage.credits = credits; // Show game over screen LK.showGameOver(); return; } // Remove alien laser that hit the ship game.removeChild(alienLaser); alienLasers.splice(al, 1); continue; } } // Update asteroids for (var m = asteroids.length - 1; m >= 0; m--) { var asteroid = asteroids[m]; asteroid.update(); // Remove asteroids that go off screen if (asteroid.y > 2832) { game.removeChild(asteroid); asteroids.splice(m, 1); continue; } // Check collision with ship if (ship && asteroid.intersects(ship)) { // Ship takes damage based on asteroid size var damage = asteroid.size === 'large' ? 25 : 10; var gameOver = ship.takeDamage(damage); if (gameOver) { // Check if a new high score was achieved if (score > storage.highScore) { storage.highScore = score; } // Save credits earned storage.credits = credits; // Show game over screen LK.showGameOver(); return; } // Remove asteroid that hit the ship game.removeChild(asteroid); asteroids.splice(m, 1); // Flash screen to indicate damage LK.effects.flashScreen(0xFF0000, 300); continue; } } // Update resources for (var n = resources.length - 1; n >= 0; n--) { var resource = resources[n]; resource.update(); // Check if collected by ship if (ship && resource.intersects(ship)) { var value = resource.collect(); if (value > 0) { // Add to credits credits += value; creditsTxt.setText('Credits: ' + credits); // Store credits storage.credits = credits; // Play collection sound LK.getSound('collectResource').play(); // Add to score score += value; scoreTxt.setText('Score: ' + score); // Remove after animation completes LK.setTimeout(function () { if (resources.indexOf(resource) !== -1) { game.removeChild(resource); resources.splice(resources.indexOf(resource), 1); } }, 500); } } // Remove resources that go off screen if (resource.y > 2832) { game.removeChild(resource); resources.splice(n, 1); continue; } } // Update stars background for (var s = 0; s < stars.length; s++) { stars[s].update(); } // Update radar to include aliens radar.updateRadar([].concat(_toConsumableArray(asteroids), _toConsumableArray(aliens))); // Update map if player ship exists if (ship && map) { // Combine all game objects for the map var allObjects = [].concat(_toConsumableArray(asteroids), _toConsumableArray(aliens), _toConsumableArray(resources)); // Update map with current positions map.updateMap({ x: ship.x, y: ship.y }, allObjects); } // Update UI updateUI(); }; // Start the game initGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
credits: 0,
laserLevel: 1,
shieldLevel: 1,
engineLevel: 1,
highScore: 0
});
/****
* Classes
****/
var Alien = Container.expand(function () {
var self = Container.call(this);
self.health = 75;
self.size = 'alien';
self.value = 15;
// Create pixel art alien ship
// Main body - larger central pixel
var alienGraphics = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.5,
tint: 0x9933ff // Purple alien ship
});
// Create alien ship details with smaller blocks
// Top section
var topSection = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.2,
tint: 0xcc66ff // Lighter purple
});
topSection.y = -20;
self.addChild(topSection);
// Bottom section
var bottomSection = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.2,
tint: 0xcc66ff // Lighter purple
});
bottomSection.y = 20;
self.addChild(bottomSection);
// Left wing
var leftWing = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: 0x6600cc // Darker purple
});
leftWing.x = -30;
self.addChild(leftWing);
// Right wing
var rightWing = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: 0x6600cc // Darker purple
});
rightWing.x = 30;
self.addChild(rightWing);
// Cockpit glow - central pixel
var cockpit = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
tint: 0xff33cc // Pink glow
});
cockpit.y = -5;
self.addChild(cockpit);
// Random movement pattern
self.vx = Math.random() * 4 - 2;
self.vy = Math.random() * 2 + 1;
self.fireTimer = Math.floor(Math.random() * 60);
self.targetX = 0;
self.targetY = 0;
self.update = function () {
// Move in a slight sine wave pattern
self.x += self.vx + Math.sin(LK.ticks / 20) * 1.5;
self.y += self.vy;
// Occasionally change horizontal direction
if (LK.ticks % 120 === 0) {
self.vx = Math.random() * 4 - 2;
}
// Wrap around screen edges horizontally
if (self.x < -60) {
self.x = 2108;
}
if (self.x > 2108) {
self.x = -60;
}
// Target the ship if it exists
if (ship) {
self.targetX = ship.x;
self.targetY = ship.y;
}
// Fire timer for shooting at player
self.fireTimer++;
};
self.takeDamage = function (amount) {
self.health -= amount;
// Visual feedback
tween(alienGraphics, {
tint: 0xff8800
}, {
duration: 100,
onFinish: function onFinish() {
tween(alienGraphics, {
tint: 0x2ecc71
}, {
duration: 200
});
}
});
return self.health <= 0;
};
self.split = function () {
var fragments = [];
// Create resources
for (var i = 0; i < self.value; i++) {
var resource = new Resource();
resource.x = self.x + (Math.random() * 60 - 30);
resource.y = self.y + (Math.random() * 60 - 30);
resource.vx = Math.random() * 4 - 2;
resource.vy = Math.random() * 4 - 2 + self.vy;
fragments.push(resource);
}
return fragments;
};
return self;
});
var AlienLaser = Container.expand(function () {
var self = Container.call(this);
// Main pixel for alien laser
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 1.0,
tint: 0xff3366 // Pink-red alien laser
});
// Add pixel art detail - laser head
var laserHead = LK.getAsset('laser', {
anchorX: 0.5,
anchorY: 0.0,
scaleX: 1.0,
scaleY: 0.3,
tint: 0xff99aa // Lighter pinkish
});
self.addChild(laserHead);
// Add pixel art detail - laser trail
var laserTrail = LK.getAsset('laser', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.5,
scaleY: 0.4,
tint: 0xcc0033 // Darker red
});
laserTrail.y = 15;
self.addChild(laserTrail);
self.speed = 10;
self.power = 15;
self.targetX = 0;
self.targetY = 0;
self.vx = 0;
self.vy = 0;
self.setup = function (startX, startY, targetX, targetY) {
self.x = startX;
self.y = startY;
// Calculate direction toward target
var dx = targetX - startX;
var dy = targetY - startY;
var dist = Math.sqrt(dx * dx + dy * dy);
// Normalize and apply speed
if (dist > 0) {
self.vx = dx / dist * self.speed;
self.vy = dy / dist * self.speed;
} else {
self.vy = self.speed;
}
// Rotate laser to point in direction of movement
self.rotation = Math.atan2(dy, dx) + Math.PI / 2;
};
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
var Asteroid = Container.expand(function () {
var self = Container.call(this);
self.size = 'large';
self.value = Math.floor(Math.random() * 5) + 5;
self.health = 100;
// Create a pixel art asteroid by composing multiple blocks
var asteroidCore = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
tint: 0x888888 // Base gray color
});
// Add pixel blocks for asteroid jagged edges
var asteroidParts = [];
var numParts = 8; // Number of pixel blocks to add
for (var i = 0; i < numParts; i++) {
var angle = i / numParts * Math.PI * 2;
var distance = 30 + Math.random() * 20; // Vary distance from center
var size = 0.2 + Math.random() * 0.3; // Vary block size
// Slightly varied gray tones for pixel art effect
var tint = 0x666666 + Math.floor(Math.random() * 0x333333);
var part = LK.getAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size,
scaleY: size,
tint: tint
});
part.x = Math.cos(angle) * distance;
part.y = Math.sin(angle) * distance;
self.addChild(part);
asteroidParts.push(part);
}
// Random rotation speed
self.rotationSpeed = Math.random() * 0.02 - 0.01;
// Random velocity
self.vx = Math.random() * 2 - 1;
self.vy = Math.random() * 3 + 1;
self.update = function () {
self.rotation += self.rotationSpeed;
self.x += self.vx;
self.y += self.vy;
// Wrap around screen edges horizontally
if (self.x < -100) {
self.x = 2148;
}
if (self.x > 2148) {
self.x = -100;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
// Visual feedback
tween(asteroidCore, {
tint: 0xff8800
}, {
duration: 100,
onFinish: function onFinish() {
tween(asteroidCore, {
tint: 0x888888
}, {
duration: 200
});
}
});
return self.health <= 0;
};
self.split = function () {
var fragments = [];
if (self.size === 'large') {
// Create 2 smaller asteroids
for (var i = 0; i < 2; i++) {
var smallAsteroid = new SmallAsteroid();
smallAsteroid.x = self.x + (Math.random() * 40 - 20);
smallAsteroid.y = self.y + (Math.random() * 40 - 20);
smallAsteroid.vx = self.vx + (Math.random() * 2 - 1);
smallAsteroid.vy = self.vy + (Math.random() * 2 - 1);
fragments.push(smallAsteroid);
}
// Create resources
for (var j = 0; j < self.value; j++) {
var resource = new Resource();
resource.x = self.x + (Math.random() * 60 - 30);
resource.y = self.y + (Math.random() * 60 - 30);
resource.vx = Math.random() * 4 - 2;
resource.vy = Math.random() * 4 - 2 + self.vy;
fragments.push(resource);
}
}
return fragments;
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
// Main laser beam
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 1.2,
tint: 0x22ff44 // Bright green laser
});
// Add pixel art details to laser - head glow
var laserHead = LK.getAsset('laser', {
anchorX: 0.5,
anchorY: 0.0,
scaleX: 1.2,
scaleY: 0.3,
tint: 0x88ffaa // Lighter green for head
});
laserHead.y = -15;
self.addChild(laserHead);
// Add pixel art details to laser - tail
var laserTail = LK.getAsset('laser', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 0.6,
scaleY: 0.4,
tint: 0x118822 // Darker green for tail
});
laserTail.y = 15;
self.addChild(laserTail);
self.speed = -15;
self.power = 25;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Map = Container.expand(function () {
var self = Container.call(this);
// Create map background
var mapBg = self.attachAsset('radarBackground', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0x1a2733,
alpha: 0.7
});
// Create player position indicator
var playerMarker = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5,
tint: 0x4286f4 // Blue to match player ship
});
self.addChild(playerMarker);
// Create array to hold map markers
self.markers = [];
// Update map with game objects
self.updateMap = function (playerPos, gameObjects) {
// Position player marker at center
playerMarker.x = 0;
playerMarker.y = 0;
// Clear existing markers
for (var i = 0; i < self.markers.length; i++) {
self.removeChild(self.markers[i]);
}
self.markers = [];
// Map dimensions
var mapWidth = mapBg.width;
var mapHeight = mapBg.height;
// Add markers for game objects
for (var i = 0; i < gameObjects.length; i++) {
var obj = gameObjects[i];
// Calculate relative position
var relX = (obj.x - playerPos.x) / 800; // Scale down game world
var relY = (obj.y - playerPos.y) / 800;
// If within map bounds
if (Math.abs(relX) < mapWidth / 2 && Math.abs(relY) < mapHeight / 2) {
var marker = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
// Set position
marker.x = relX;
marker.y = relY;
// Set color based on object type
if (obj.size === 'large') {
marker.tint = 0x7f8c8d; // Gray for asteroids
} else if (obj.size === 'small') {
marker.tint = 0x95a5a6; // Light gray for small asteroids
} else if (obj.size === 'alien') {
marker.tint = 0xff0000; // Red for aliens
} else {
marker.tint = 0xf1c40f; // Yellow for resources
}
self.addChild(marker);
self.markers.push(marker);
}
}
};
return self;
});
var MiningShip = Container.expand(function () {
var self = Container.call(this);
// Create main pixel art spaceship container
var shipContainer = new Container();
self.addChild(shipContainer);
// Create ship body (main part) - center pixel block
var shipBody = self.attachAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.6,
tint: 0x4286f4 // Main ship color
});
// Create ship nose - front pixel block
var shipNose = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.3,
tint: 0x4286f4
});
shipNose.y = -30;
self.addChild(shipNose);
// Create left wing - pixel blocks
var leftWing = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
tint: 0x2255cc // Wing color
});
leftWing.x = -40;
leftWing.y = 0;
self.addChild(leftWing);
// Wing tip
var leftWingTip = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0x2255cc
});
leftWingTip.x = -60;
leftWingTip.y = 10;
self.addChild(leftWingTip);
// Create right wing - pixel blocks
var rightWing = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.4,
scaleY: 0.4,
tint: 0x2255cc // Wing color
});
rightWing.x = 40;
rightWing.y = 0;
self.addChild(rightWing);
// Wing tip
var rightWingTip = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0x2255cc
});
rightWingTip.x = 60;
rightWingTip.y = 10;
self.addChild(rightWingTip);
// Cockpit - center pixel
var cockpit = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.2,
tint: 0x22ffdd // Cockpit color
});
cockpit.y = -15;
self.addChild(cockpit);
// Engine exhausts - pixelated thruster flames
var leftExhaust = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: 0xff6600 // Orange exhaust
});
leftExhaust.x = -20;
leftExhaust.y = 30;
self.addChild(leftExhaust);
var rightExhaust = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3,
tint: 0xff6600 // Orange exhaust
});
rightExhaust.x = 20;
rightExhaust.y = 30;
self.addChild(rightExhaust);
// Small exhaust flames for pixel art effect
var leftExhaustTip = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xffcc00 // Yellow exhaust tip
});
leftExhaustTip.x = -20;
leftExhaustTip.y = 38;
self.addChild(leftExhaustTip);
var rightExhaustTip = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2,
scaleY: 0.2,
tint: 0xffcc00 // Yellow exhaust tip
});
rightExhaustTip.x = 20;
rightExhaustTip.y = 38;
self.addChild(rightExhaustTip);
// Animate engine exhausts
function animateExhausts() {
// Animate main exhausts
tween(leftExhaust, {
scaleY: 0.4,
alpha: 0.8
}, {
duration: 400,
onFinish: function onFinish() {
tween(leftExhaust, {
scaleY: 0.3,
alpha: 1.0
}, {
duration: 400,
onFinish: animateExhausts
});
}
});
tween(rightExhaust, {
scaleY: 0.4,
alpha: 0.8
}, {
duration: 400,
easing: tween.easeOut
});
// Animate exhaust tips for pixel art flame effect
tween(leftExhaustTip, {
scaleY: 0.3,
alpha: 0.9
}, {
duration: 200,
easing: tween.easeOut
});
tween(rightExhaustTip, {
scaleY: 0.3,
alpha: 0.9
}, {
duration: 200,
easing: tween.easeOut
});
}
animateExhausts();
var shieldGraphics = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
self.health = 100;
self.maxHealth = 100;
self.speed = 5;
self.laserPower = storage.laserLevel;
self.shieldStrength = storage.shieldLevel;
// Increase speed based on engine level
self.speed += storage.engineLevel;
// Make shield size based on shield level
shieldGraphics.scale.set(1 + storage.shieldLevel * 0.1);
self.activateShield = function () {
if (self.shield > 0) {
tween(shieldGraphics, {
alpha: 0.5
}, {
duration: 200,
onFinish: function onFinish() {
tween(shieldGraphics, {
alpha: 0.3
}, {
duration: 800
});
}
});
}
};
self.takeDamage = function (amount) {
var actualDamage = amount / self.shieldStrength;
self.health -= actualDamage;
if (self.health <= 0) {
self.health = 0;
}
// Flash red to indicate damage
LK.getSound('shipDamage').play();
tween(shipBody, {
tint: 0xff0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(shipBody, {
tint: 0x4286f4 // Return to original blue color
}, {
duration: 200
});
}
});
// Activate shield effect
self.activateShield();
return self.health <= 0;
};
return self;
});
var Radar = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('radarBackground', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.blips = [];
self.updateRadar = function (asteroids) {
// Clear existing blips
for (var i = 0; i < self.blips.length; i++) {
self.removeChild(self.blips[i]);
}
self.blips = [];
// Add new blips for asteroids
for (var j = 0; j < asteroids.length; j++) {
var asteroid = asteroids[j];
// Only show blips for asteroids that are off-screen or about to enter
if (asteroid.y < -100) {
var blip = LK.getAsset('radarBlip', {
anchorX: 0.5,
anchorY: 0.5
});
// Scale radar coordinates to fit in radar display
var radarX = asteroid.x / 2048 * background.width - background.width / 2;
var radarY = (asteroid.y + 300) / 800 * background.height - background.height / 2;
// Clamp to radar boundaries
radarY = Math.max(-background.height / 2, Math.min(radarY, background.height / 2));
radarX = Math.max(-background.width / 2, Math.min(radarX, background.width / 2));
blip.x = radarX;
blip.y = radarY;
// Size and color based on object type
if (asteroid.size === 'large') {
blip.scale.set(1.5);
}
// If it's an alien, make the blip red
if (asteroid.size === 'alien') {
blip.tint = 0xff0000;
blip.scale.set(1.2);
}
self.addChild(blip);
self.blips.push(blip);
}
}
};
return self;
});
var Resource = Container.expand(function () {
var self = Container.call(this);
// Create main pixel for resource
var resourceGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.value = Math.floor(Math.random() * 5) + 1;
self.collected = false;
// Set random value-based tint - higher value = more golden
var colorValue = Math.min(0xFFFFFF, 0xC0C0C0 + self.value * 0x101000);
resourceGraphics.tint = colorValue;
// Create smaller pixels around central pixel for gem-like appearance
var pixelSize = 0.3;
var pixelDistance = 8;
// Add 4 smaller pixels in a + pattern around the main resource
for (var i = 0; i < 4; i++) {
var angle = i / 4 * Math.PI * 2;
var pixelX = Math.cos(angle) * pixelDistance;
var pixelY = Math.sin(angle) * pixelDistance;
var pixel = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: pixelSize,
scaleY: pixelSize,
tint: 0xFFFFFF // Brighter to create highlight effect
});
pixel.x = pixelX;
pixel.y = pixelY;
pixel.alpha = 0.8;
self.addChild(pixel);
}
// Random velocity
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
// Gradually slow down
self.vx *= 0.98;
self.vy *= 0.98;
// Resource magnetized to ship when close enough
if (ship && !self.collected) {
var dx = ship.x - self.x;
var dy = ship.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
// Apply force proportional to distance
var strength = (1 - distance / 200) * 0.5;
self.vx += dx * strength;
self.vy += dy * strength;
}
}
};
self.collect = function () {
if (!self.collected) {
self.collected = true;
// Animation for collection
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
easing: tween.easeOut
});
return self.value;
}
return 0;
};
return self;
});
var SmallAsteroid = Container.expand(function () {
var self = Container.call(this);
self.size = 'small';
self.value = Math.floor(Math.random() * 3) + 1;
self.health = 50;
// Create a pixel art small asteroid core
var asteroidGraphics = self.attachAsset('smallAsteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6,
tint: 0x777777
});
// Add smaller pixel blocks for jagged edges
var numParts = 5; // Fewer parts for smaller asteroid
for (var i = 0; i < numParts; i++) {
var angle = i / numParts * Math.PI * 2;
var distance = 15 + Math.random() * 10; // Smaller distance
var size = 0.15 + Math.random() * 0.2; // Smaller blocks
// Slightly varied gray tones
var tint = 0x666666 + Math.floor(Math.random() * 0x222222);
var part = LK.getAsset('smallAsteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: size,
scaleY: size,
tint: tint
});
part.x = Math.cos(angle) * distance;
part.y = Math.sin(angle) * distance;
self.addChild(part);
}
// Random rotation speed
self.rotationSpeed = Math.random() * 0.04 - 0.02;
// Random velocity
self.vx = Math.random() * 3 - 1.5;
self.vy = Math.random() * 3 + 2;
self.update = function () {
self.rotation += self.rotationSpeed;
self.x += self.vx;
self.y += self.vy;
// Wrap around screen edges horizontally
if (self.x < -50) {
self.x = 2098;
}
if (self.x > 2098) {
self.x = -50;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
// Visual feedback
tween(asteroidGraphics, {
tint: 0xff8800
}, {
duration: 100,
onFinish: function onFinish() {
tween(asteroidGraphics, {
tint: 0x777777
}, {
duration: 200
});
}
});
return self.health <= 0;
};
self.split = function () {
var fragments = [];
// Create resources
for (var i = 0; i < self.value; i++) {
var resource = new Resource();
resource.x = self.x + (Math.random() * 30 - 15);
resource.y = self.y + (Math.random() * 30 - 15);
resource.vx = Math.random() * 3 - 1.5;
resource.vy = Math.random() * 3 - 1.5 + self.vy;
fragments.push(resource);
}
return fragments;
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
// Create a pixel art star
var starSize = 0.1 + Math.random() * 0.4; // Vary star sizes
var brightness = 0.5 + Math.random() * 0.5; // Vary star brightness
// Create the star shape (using a small resource asset for the star point)
var starGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: starSize,
scaleY: starSize,
tint: 0xFFFFFF // White star
});
starGraphics.alpha = brightness;
// Star twinkle effect
function twinkle() {
// Random twinkle duration
var duration = 1000 + Math.random() * 2000;
// Random target alpha for twinkling
var targetAlpha = 0.2 + Math.random() * 0.8;
tween(starGraphics, {
alpha: targetAlpha
}, {
duration: duration,
onFinish: twinkle
});
}
// Start twinkling with a random delay
LK.setTimeout(twinkle, Math.random() * 3000);
// Parallax scrolling speed (deeper stars move slower)
self.scrollSpeed = 0.1 + Math.random() * 0.4;
self.update = function () {
// Move star down very slowly (parallax effect)
self.y += self.scrollSpeed;
// Wrap around when it goes off screen
if (self.y > 2732) {
self.y = -10;
self.x = Math.random() * 2048;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) {
return _arrayLikeToArray(r, a);
}
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) {
return Array.from(r);
}
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) {
return _arrayLikeToArray(r);
}
}
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) {
n[e] = r[e];
}
return n;
}
game.setBackgroundColor(0x0A0A2A); // Deep space blue
// Game state variables
var ship;
var lasers = [];
var asteroids = [];
var resources = [];
var aliens = [];
var alienLasers = [];
var stars = []; // Array to hold background stars
var map; // Map object for HUD
var gameLevel = 1;
var spawnTimer = 0;
var spawnInterval = 120; // Frames between asteroid spawns
var alienSpawnTimer = 0;
var alienSpawnInterval = 600; // Frames between alien spawns
var levelTimer = 0;
var levelDuration = 1800; // 30 seconds at 60fps
var score = 0;
var credits = storage.credits || 0;
var levelUpPopupVisible = false;
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 30,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -200;
scoreTxt.y = 20;
var creditsTxt = new Text2('Credits: ' + credits, {
size: 30,
fill: 0xFFDD00
});
creditsTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(creditsTxt);
creditsTxt.x = -200;
creditsTxt.y = 60;
var levelTxt = new Text2('Level: ' + gameLevel, {
size: 30,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(levelTxt);
levelTxt.x = -200;
levelTxt.y = 100;
var healthBar = new Container();
var healthBarBg = LK.getAsset('miningShip', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.3,
tint: 0x444444
});
var healthBarFill = LK.getAsset('miningShip', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.25,
tint: 0x00FF00
});
healthBar.addChild(healthBarBg);
healthBar.addChild(healthBarFill);
healthBar.x = 120;
healthBar.y = 30;
LK.gui.topLeft.addChild(healthBar);
// Upgrade UI section (initially hidden)
var upgradeContainer = new Container();
upgradeContainer.visible = false;
LK.gui.center.addChild(upgradeContainer);
var upgradePanel = LK.getAsset('radarBackground', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2.5,
tint: 0x223344
});
upgradeContainer.addChild(upgradePanel);
var upgradeTitle = new Text2('UPGRADE SHIP', {
size: 50,
fill: 0xFFFFFF
});
upgradeTitle.anchor.set(0.5, 0);
upgradeTitle.y = -200;
upgradeContainer.addChild(upgradeTitle);
var laserUpgradeBtn = new Container();
laserUpgradeBtn.y = -100;
upgradeContainer.addChild(laserUpgradeBtn);
var laserBtnBg = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 0.6,
tint: 0x2ecc71
});
laserUpgradeBtn.addChild(laserBtnBg);
var laserBtnTxt = new Text2('Laser Lvl ' + storage.laserLevel + ' → ' + (storage.laserLevel + 1) + ' (Cost: 100)', {
size: 25,
fill: 0xFFFFFF
});
laserBtnTxt.anchor.set(0.5, 0.5);
laserUpgradeBtn.addChild(laserBtnTxt);
var shieldUpgradeBtn = new Container();
shieldUpgradeBtn.y = 0;
upgradeContainer.addChild(shieldUpgradeBtn);
var shieldBtnBg = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 0.6,
tint: 0x3498db
});
shieldUpgradeBtn.addChild(shieldBtnBg);
var shieldBtnTxt = new Text2('Shield Lvl ' + storage.shieldLevel + ' → ' + (storage.shieldLevel + 1) + ' (Cost: 150)', {
size: 25,
fill: 0xFFFFFF
});
shieldBtnTxt.anchor.set(0.5, 0.5);
shieldUpgradeBtn.addChild(shieldBtnTxt);
var engineUpgradeBtn = new Container();
engineUpgradeBtn.y = 100;
upgradeContainer.addChild(engineUpgradeBtn);
var engineBtnBg = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 0.6,
tint: 0xf39c12
});
engineUpgradeBtn.addChild(engineBtnBg);
var engineBtnTxt = new Text2('Engine Lvl ' + storage.engineLevel + ' → ' + (storage.engineLevel + 1) + ' (Cost: 125)', {
size: 25,
fill: 0xFFFFFF
});
engineBtnTxt.anchor.set(0.5, 0.5);
engineUpgradeBtn.addChild(engineBtnTxt);
var continueBtn = new Container();
continueBtn.y = 200;
upgradeContainer.addChild(continueBtn);
var continueBtnBg = LK.getAsset('miningShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 0.6,
tint: 0xe74c3c
});
continueBtn.addChild(continueBtnBg);
var continueBtnTxt = new Text2('CONTINUE MINING', {
size: 30,
fill: 0xFFFFFF
});
continueBtnTxt.anchor.set(0.5, 0.5);
continueBtn.addChild(continueBtnTxt);
// Radar system at bottom
var radar = new Radar();
radar.x = 2048 / 2;
radar.y = 2732 - 120;
game.addChild(radar);
// Initialize the ship
function initShip() {
ship = new MiningShip();
ship.x = 2048 / 2;
ship.y = 2732 - 400;
game.addChild(ship);
}
// Initialize stars for the background
function initStars() {
// Create a good number of stars for the background
var numStars = 150;
// Clear any existing stars first
for (var i = 0; i < stars.length; i++) {
if (stars[i].parent) {
stars[i].parent.removeChild(stars[i]);
}
}
stars = [];
// Create and position new stars
for (var i = 0; i < numStars; i++) {
var star = new Star();
// Position randomly across the entire screen
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
// Add to game (behind other elements)
game.addChildAt(star, 0);
stars.push(star);
}
}
// Initialize game
function initGame() {
// Start with a clean slate
clearGameElements();
// Load credits from storage
credits = storage.credits || 0;
// Initialize stars for background
initStars();
// Initialize ship
initShip();
// Reset game state
gameLevel = 1;
score = 0;
spawnTimer = 0;
alienSpawnTimer = 0;
levelTimer = 0;
levelUpPopupVisible = false;
// Initialize map
if (map && map.parent) {
map.parent.removeChild(map);
}
map = new Map();
map.x = 120;
map.y = 180;
LK.gui.topLeft.addChild(map);
// Update UI
updateUI();
// Start background music
LK.playMusic('spaceAmbience');
}
// Clear all game elements
function clearGameElements() {
// Remove all asteroids
for (var i = 0; i < asteroids.length; i++) {
if (asteroids[i].parent) {
asteroids[i].parent.removeChild(asteroids[i]);
}
}
asteroids = [];
// Remove all lasers
for (var j = 0; j < lasers.length; j++) {
if (lasers[j].parent) {
lasers[j].parent.removeChild(lasers[j]);
}
}
lasers = [];
// Remove all resources
for (var k = 0; k < resources.length; k++) {
if (resources[k].parent) {
resources[k].parent.removeChild(resources[k]);
}
}
resources = [];
// Remove all aliens
for (var a = 0; a < aliens.length; a++) {
if (aliens[a].parent) {
aliens[a].parent.removeChild(aliens[a]);
}
}
aliens = [];
// Remove all alien lasers
for (var al = 0; al < alienLasers.length; al++) {
if (alienLasers[al].parent) {
alienLasers[al].parent.removeChild(alienLasers[al]);
}
}
alienLasers = [];
// Remove all stars
for (var s = 0; s < stars.length; s++) {
if (stars[s].parent) {
stars[s].parent.removeChild(stars[s]);
}
}
stars = [];
// Remove ship if it exists
if (ship && ship.parent) {
ship.parent.removeChild(ship);
}
// Hide upgrade panel
upgradeContainer.visible = false;
// Remove map if it exists
if (map && map.parent) {
map.parent.removeChild(map);
}
}
// Update UI elements
function updateUI() {
scoreTxt.setText('Score: ' + score);
creditsTxt.setText('Credits: ' + credits);
levelTxt.setText('Level: ' + gameLevel);
// Update health bar
if (ship) {
healthBarFill.scale.x = 2 * (ship.health / ship.maxHealth);
// Change color based on health
if (ship.health > 70) {
healthBarFill.tint = 0x00FF00;
} else if (ship.health > 30) {
healthBarFill.tint = 0xFFAA00;
} else {
healthBarFill.tint = 0xFF0000;
}
}
// Update upgrade buttons
laserBtnTxt.setText('Laser Lvl ' + storage.laserLevel + ' → ' + (storage.laserLevel + 1) + ' (Cost: 100)');
shieldBtnTxt.setText('Shield Lvl ' + storage.shieldLevel + ' → ' + (storage.shieldLevel + 1) + ' (Cost: 150)');
engineBtnTxt.setText('Engine Lvl ' + storage.engineLevel + ' → ' + (storage.engineLevel + 1) + ' (Cost: 125)');
}
// Spawn an asteroid
function spawnAsteroid() {
var asteroid = new Asteroid();
asteroid.x = Math.random() * 2048;
asteroid.y = -200;
// Adjust velocity based on level
asteroid.vy = 1 + gameLevel * 0.5;
if (gameLevel > 5) {
// More horizontal movement in higher levels
asteroid.vx = (Math.random() * 3 - 1.5) * (gameLevel * 0.2);
}
asteroids.push(asteroid);
game.addChild(asteroid);
}
// Spawn an alien ship
function spawnAlien() {
var alien = new Alien();
alien.x = Math.random() * 2048;
alien.y = -200;
// Adjust velocity based on level
alien.vy = 0.8 + gameLevel * 0.3;
aliens.push(alien);
game.addChild(alien);
}
// Alien fires a laser at the player
function fireAlienLaser(alien) {
var laser = new AlienLaser();
laser.setup(alien.x, alien.y, alien.targetX, alien.targetY);
alienLasers.push(laser);
game.addChild(laser);
}
// Fire a laser from the ship
function fireLaser() {
var laser = new Laser();
laser.x = ship.x;
laser.y = ship.y - 40;
laser.power = 25 * ship.laserPower;
lasers.push(laser);
game.addChild(laser);
LK.getSound('laserSound').play();
}
// Show upgrade UI between levels
function showUpgradeUI() {
upgradeContainer.visible = true;
levelUpPopupVisible = true;
// Update button texts
laserBtnTxt.setText('Laser Lvl ' + storage.laserLevel + ' → ' + (storage.laserLevel + 1) + ' (Cost: 100)');
shieldBtnTxt.setText('Shield Lvl ' + storage.shieldLevel + ' → ' + (storage.shieldLevel + 1) + ' (Cost: 150)');
engineBtnTxt.setText('Engine Lvl ' + storage.engineLevel + ' → ' + (storage.engineLevel + 1) + ' (Cost: 125)');
// Update button colors based on affordability
laserBtnBg.tint = credits >= 100 ? 0x2ecc71 : 0x95a5a6;
shieldBtnBg.tint = credits >= 150 ? 0x3498db : 0x95a5a6;
engineBtnBg.tint = credits >= 125 ? 0xf39c12 : 0x95a5a6;
}
// Hide upgrade UI
function hideUpgradeUI() {
upgradeContainer.visible = false;
levelUpPopupVisible = false;
// Reinitialize ship with new upgrades
if (ship && ship.parent) {
ship.parent.removeChild(ship);
}
initShip();
}
// Handle upgrade button clicks
function handleUpgradeClick(x, y) {
if (!levelUpPopupVisible) {
return;
}
// Convert global coordinates to local coordinates for the upgrade container
var local = upgradeContainer.toLocal({
x: x,
y: y
});
// Check if laser upgrade button was clicked
if (local.y > -130 && local.y < -70 && local.x > -150 && local.x < 150 && credits >= 100) {
// Upgrade laser
credits -= 100;
storage.laserLevel += 1;
storage.credits = credits;
updateUI();
// Visual feedback
tween(laserUpgradeBtn, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(laserUpgradeBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
// Check if shield upgrade button was clicked
else if (local.y > -30 && local.y < 30 && local.x > -150 && local.x < 150 && credits >= 150) {
// Upgrade shield
credits -= 150;
storage.shieldLevel += 1;
storage.credits = credits;
updateUI();
// Visual feedback
tween(shieldUpgradeBtn, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(shieldUpgradeBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
// Check if engine upgrade button was clicked
else if (local.y > 70 && local.y < 130 && local.x > -150 && local.x < 150 && credits >= 125) {
// Upgrade engine
credits -= 125;
storage.engineLevel += 1;
storage.credits = credits;
updateUI();
// Visual feedback
tween(engineUpgradeBtn, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(engineUpgradeBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
// Check if continue button was clicked
else if (local.y > 170 && local.y < 230 && local.x > -150 && local.x < 150) {
// Continue to next level
hideUpgradeUI();
// Visual feedback
tween(continueBtn, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(continueBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
}
// Mouse/touch events
var dragMode = false;
var lastX = 0;
game.down = function (x, y, obj) {
// Handle upgrade UI clicks if visible
if (levelUpPopupVisible) {
handleUpgradeClick(x, y);
return;
}
// Start tracking for ship movement
dragMode = true;
lastX = x;
// Fire laser when tapping/clicking
if (ship && !levelUpPopupVisible) {
fireLaser();
}
};
game.up = function (x, y, obj) {
dragMode = false;
};
game.move = function (x, y, obj) {
if (dragMode && ship && !levelUpPopupVisible) {
// Move ship based on drag distance
var dx = x - lastX;
ship.x += dx * 1.5;
// Constrain to screen
ship.x = Math.max(50, Math.min(ship.x, 2048 - 50));
lastX = x;
}
};
// Game logic update
game.update = function () {
if (levelUpPopupVisible) {
// Only handle UI events when upgrade screen is visible
return;
}
// Spawning logic
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnTimer = 0;
spawnAsteroid();
// Adjust spawn rate based on level
spawnInterval = Math.max(30, 120 - gameLevel * 10);
}
// Alien spawning logic
alienSpawnTimer++;
if (alienSpawnTimer >= alienSpawnInterval && gameLevel >= 2) {
alienSpawnTimer = 0;
spawnAlien();
// Adjust spawn rate based on level
alienSpawnInterval = Math.max(300, 600 - gameLevel * 50);
}
// Level progression
levelTimer++;
if (levelTimer >= levelDuration) {
levelTimer = 0;
gameLevel++;
levelTxt.setText('Level: ' + gameLevel);
// Show upgrade UI between levels
showUpgradeUI();
// Save progress
storage.credits = credits;
}
// Update ship if it exists
if (ship) {
// Constrain to screen
ship.x = Math.max(50, Math.min(ship.x, 2048 - 50));
}
// Update lasers
for (var i = lasers.length - 1; i >= 0; i--) {
var laser = lasers[i];
laser.update();
// Remove lasers that go off screen
if (laser.y < -50) {
game.removeChild(laser);
lasers.splice(i, 1);
continue;
}
// Check for collision with asteroids
for (var j = asteroids.length - 1; j >= 0; j--) {
var asteroid = asteroids[j];
if (laser.intersects(asteroid)) {
// Apply damage to asteroid
var destroyed = asteroid.takeDamage(laser.power);
if (destroyed) {
// Break asteroid
LK.getSound('asteroidBreak').play();
// Get fragments (smaller asteroids and resources)
var fragments = asteroid.split();
// Add fragments to the game
for (var k = 0; k < fragments.length; k++) {
var fragment = fragments[k];
if (fragment instanceof SmallAsteroid) {
asteroids.push(fragment);
game.addChild(fragment);
} else if (fragment instanceof Resource) {
resources.push(fragment);
game.addChild(fragment);
}
}
// Remove the destroyed asteroid
game.removeChild(asteroid);
asteroids.splice(j, 1);
// Add to score
score += 10;
scoreTxt.setText('Score: ' + score);
}
// Remove the laser that hit
game.removeChild(laser);
lasers.splice(i, 1);
break;
}
}
// Check for collision with aliens
for (var a = aliens.length - 1; a >= 0; a--) {
var alien = aliens[a];
if (laser.intersects(alien)) {
// Apply damage to alien
var alienDestroyed = alien.takeDamage(laser.power);
if (alienDestroyed) {
// Get resources from destroyed alien
var alienFragments = alien.split();
// Add fragments to the game
for (var af = 0; af < alienFragments.length; af++) {
var alienFragment = alienFragments[af];
if (alienFragment instanceof Resource) {
resources.push(alienFragment);
game.addChild(alienFragment);
}
}
// Remove the destroyed alien
game.removeChild(alien);
aliens.splice(a, 1);
// Add to score
score += 25;
scoreTxt.setText('Score: ' + score);
}
// Remove the laser that hit
game.removeChild(laser);
lasers.splice(i, 1);
break;
}
}
}
// Update aliens
for (var al = aliens.length - 1; al >= 0; al--) {
var alien = aliens[al];
alien.update();
// Remove aliens that go off screen
if (alien.y > 2832) {
game.removeChild(alien);
aliens.splice(al, 1);
continue;
}
// Occasionally fire at player if in range
if (alien.fireTimer >= 120 && ship) {
// Reset fire timer
alien.fireTimer = 0;
// Only fire if within reasonable range
var dx = Math.abs(ship.x - alien.x);
if (dx < 500) {
fireAlienLaser(alien);
}
}
// Check collision with ship
if (ship && alien.intersects(ship)) {
// Ship takes damage from alien collision
var alienDamage = 30;
var gameOver = ship.takeDamage(alienDamage);
if (gameOver) {
// Check if a new high score was achieved
if (score > storage.highScore) {
storage.highScore = score;
}
// Save credits earned
storage.credits = credits;
// Show game over screen
LK.showGameOver();
return;
}
// Remove alien that hit the ship
game.removeChild(alien);
aliens.splice(al, 1);
// Flash screen to indicate damage
LK.effects.flashScreen(0xFF0000, 300);
continue;
}
}
// Update alien lasers
for (var al = alienLasers.length - 1; al >= 0; al--) {
var alienLaser = alienLasers[al];
alienLaser.update();
// Remove alien lasers that go off screen
if (alienLaser.y > 2832 || alienLaser.y < -50 || alienLaser.x < -50 || alienLaser.x > 2098) {
game.removeChild(alienLaser);
alienLasers.splice(al, 1);
continue;
}
// Check collision with ship
if (ship && alienLaser.intersects(ship)) {
// Ship takes damage from alien laser
var laserDamage = 20;
var gameOver = ship.takeDamage(laserDamage);
if (gameOver) {
// Check if a new high score was achieved
if (score > storage.highScore) {
storage.highScore = score;
}
// Save credits earned
storage.credits = credits;
// Show game over screen
LK.showGameOver();
return;
}
// Remove alien laser that hit the ship
game.removeChild(alienLaser);
alienLasers.splice(al, 1);
continue;
}
}
// Update asteroids
for (var m = asteroids.length - 1; m >= 0; m--) {
var asteroid = asteroids[m];
asteroid.update();
// Remove asteroids that go off screen
if (asteroid.y > 2832) {
game.removeChild(asteroid);
asteroids.splice(m, 1);
continue;
}
// Check collision with ship
if (ship && asteroid.intersects(ship)) {
// Ship takes damage based on asteroid size
var damage = asteroid.size === 'large' ? 25 : 10;
var gameOver = ship.takeDamage(damage);
if (gameOver) {
// Check if a new high score was achieved
if (score > storage.highScore) {
storage.highScore = score;
}
// Save credits earned
storage.credits = credits;
// Show game over screen
LK.showGameOver();
return;
}
// Remove asteroid that hit the ship
game.removeChild(asteroid);
asteroids.splice(m, 1);
// Flash screen to indicate damage
LK.effects.flashScreen(0xFF0000, 300);
continue;
}
}
// Update resources
for (var n = resources.length - 1; n >= 0; n--) {
var resource = resources[n];
resource.update();
// Check if collected by ship
if (ship && resource.intersects(ship)) {
var value = resource.collect();
if (value > 0) {
// Add to credits
credits += value;
creditsTxt.setText('Credits: ' + credits);
// Store credits
storage.credits = credits;
// Play collection sound
LK.getSound('collectResource').play();
// Add to score
score += value;
scoreTxt.setText('Score: ' + score);
// Remove after animation completes
LK.setTimeout(function () {
if (resources.indexOf(resource) !== -1) {
game.removeChild(resource);
resources.splice(resources.indexOf(resource), 1);
}
}, 500);
}
}
// Remove resources that go off screen
if (resource.y > 2832) {
game.removeChild(resource);
resources.splice(n, 1);
continue;
}
}
// Update stars background
for (var s = 0; s < stars.length; s++) {
stars[s].update();
}
// Update radar to include aliens
radar.updateRadar([].concat(_toConsumableArray(asteroids), _toConsumableArray(aliens)));
// Update map if player ship exists
if (ship && map) {
// Combine all game objects for the map
var allObjects = [].concat(_toConsumableArray(asteroids), _toConsumableArray(aliens), _toConsumableArray(resources));
// Update map with current positions
map.updateMap({
x: ship.x,
y: ship.y
}, allObjects);
}
// Update UI
updateUI();
};
// Start the game
initGame();