Code edit (2 edits merged)
Please save this source code
User prompt
Do not make the ship disappear when trying to shoot lasers
User prompt
Ensure that players with a score if 200+ points get a new available ship every 100 points
User prompt
If only one ship is on the solar system, make it immune to asteroids until another ship is placed
User prompt
When an asteroid hits a ship, flash the ship a dim red and remove it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Make got it text button slightly lower
User prompt
Make got it text button slightly lower on the screen
Code edit (4 edits merged)
Please save this source code
User prompt
Make asteroids fly behind text on instruction screen instead of overtop of
User prompt
increase size range of asteroids to 45x45 - 70x70
User prompt
Make sure Neptune orbit’s the outer ring, not mercury
User prompt
make sure the Neptune asset orbits the outer ring of the solar system, not the earth asset
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'return entry !== null;' Line Number: 445 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard = literalLeaderboard;' Line Number: 418 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard = updatedLeaderboard;' Line Number: 411 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'leaderboard.push(newEntry);' Line Number: 393
User prompt
Add a leaderboard page when the game ends, displaying the ten top scores and the username of the player that got it ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Randomize the size of every asteroid, as long as the size is 30x30 or anywhere in between there and 60x60
User prompt
Ensure that after 200 points, a new ship is available after every 100 points
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Asteroid = Container.expand(function () { var self = Container.call(this); var asteroidGraphics = self.attachAsset('asteroid', { anchorX: 0.5, anchorY: 0.5 }); // Randomize asteroid size between 45x45 and 70x70 // Base asset is 60x60, so scale range is 0.75 to 1.17 var randomScale = 0.75 + Math.random() * 0.42; // Random value between 0.75 and 1.17 asteroidGraphics.scaleX = randomScale; asteroidGraphics.scaleY = randomScale; self.velocityX = 0; self.velocityY = 0; self.targetPlanet = null; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; asteroidGraphics.rotation += 0.05; }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; }; return self; }); var Laser = Container.expand(function () { var self = Container.call(this); var laserGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); laserGraphics.tint = 0x00ff00; // Green laser color laserGraphics.scaleX = 0.5; // Make laser thinner laserGraphics.scaleY = 2; // Make laser longer self.velocityX = 0; self.velocityY = 0; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; }; return self; }); var OrbitLine = Container.expand(function (radius) { var self = Container.call(this); self.orbitRadius = radius; // Create a single connected circular line using small line segments var numSegments = Math.max(16, Math.floor(radius * 0.1)); // Fewer segments for better performance var twoPi = Math.PI * 2; // Cache the calculation for (var i = 0; i < numSegments; i++) { var angle1 = i / numSegments * twoPi; var angle2 = (i + 1) / numSegments * twoPi; var x1 = Math.cos(angle1) * radius; var y1 = Math.sin(angle1) * radius; var x2 = Math.cos(angle2) * radius; var y2 = Math.sin(angle2) * radius; // Calculate segment length and angle var segmentLength = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); var segmentAngle = Math.atan2(y2 - y1, x2 - x1); // Create line segment var lineSegment = self.attachAsset('orbitLine', { anchorX: 0, anchorY: 0.5, alpha: 0.4, scaleX: segmentLength / 2, // Scale to match segment length scaleY: 1 }); // Position and rotate the segment lineSegment.x = x1; lineSegment.y = y1; lineSegment.rotation = segmentAngle; } return self; }); var Planet = Container.expand(function (size, color, orbitRadius, orbitSpeed) { var self = Container.call(this); self.orbitRadius = orbitRadius; self.orbitSpeed = orbitSpeed; self.angle = Math.random() * Math.PI * 2; var assetName = 'mercury'; if (color === 0x4169e1) { assetName = 'earth'; } else if (color === 0xff4500) { assetName = 'mars'; } else if (color === 0xffc649) { assetName = 'venus'; } else if (color === 0xd2691e) { assetName = 'jupiter'; } else if (color === 0xffd700) { assetName = 'saturn'; } else if (color === 0x40e0d0) { assetName = 'uranus'; } else if (color === 0x0080ff) { assetName = 'neptune'; } var planetGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { self.angle += self.orbitSpeed; var cosAngle = Math.cos(self.angle); var sinAngle = Math.sin(self.angle); self.x = sunX + cosAngle * self.orbitRadius; self.y = sunY + sinAngle * self.orbitRadius; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000011 }); /**** * Game Code ****/ // Show instructions before game starts var instructionText = new Text2(" How to play:\n\nGoal:\n- protect the Earth from asteroid collisions\n- you will be given a spaceship that shoots lasers\n- you will use these lasers to destroy asteroids\n- if the Earth gets hit with 4 asteroids, you lose\n- if you have multiple spaceships, they will all fire where you choose\n\nPoints:\n- every asteroid you destroy will earn you five points\n- every 50 points, you will recieve a new spaceship you can put in the solar system\n- if you reach 200 points, that interval will increase to every 100 points\n- with a price of 75 points, you can buy a laser upgrade that randomly applies to one ship in play, giving it the ability to shoot two lasers instead of one\n\nAsteroids:\n- asteroids are your enimies\n- they can be destroyed with one laser hit\n- they will come from random directions, so be aware of all sides of the screen\n- planets are you friends, all planets other than Earth deflect asteroids\n- if a ship gets hit with an asteroid, it will be removed, so keep a lookout for your ships\n\nControls:\n- select a spaceship until it shrinks, then click and drag it to move it, release to place it\n- click any point on the sreen to fire lasers in that direction\n- if you have multiple spaceships, they will all fire where you choose", { size: 60, fill: 0xFFFFFF, wordWrap: true, wordWrapWidth: 1600 }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 2048 / 2; instructionText.y = 2732 / 2 - 100; game.addChild(instructionText); // Add separate "Got it!" button text var gotItText = new Text2("Got it!", { size: 80, fill: 0xFFFFFF }); gotItText.anchor.set(0.5, 0.5); gotItText.x = 2048 / 2; gotItText.y = 2732 - 200; // Position below instructions, above bottom of screen game.addChild(gotItText); // Add spinning earth to top right corner of instructions var instructionEarth = LK.getAsset('earth', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 3, x: 2048 - 200, y: 200 }); game.addChild(instructionEarth); // Add defensive ship next to spinning earth var instructionShip = LK.getAsset('defensiveShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, x: 2048 - 450, y: 200 }); game.addChild(instructionShip); // Start spinning animation function spinEarth() { tween(instructionEarth, { rotation: instructionEarth.rotation + Math.PI * 2 }, { duration: 3000, easing: tween.linear, onFinish: function onFinish() { if (instructionsVisible) { spinEarth(); } } }); } spinEarth(); // Add click handler to dismiss instructions var instructionsVisible = true; var instructionAsteroids = []; var instructionAsteroidSpawnTimer = 0; game.down = function (x, y, obj) { if (instructionsVisible) { // Check if "Got it!" button was clicked var gotItClickArea = { x: gotItText.x - gotItText.width / 2 - 50, y: gotItText.y - gotItText.height / 2 - 25, width: gotItText.width + 100, height: gotItText.height + 50 }; if (x >= gotItClickArea.x && x <= gotItClickArea.x + gotItClickArea.width && y >= gotItClickArea.y && y <= gotItClickArea.y + gotItClickArea.height) { // Hide instructions and start the game instructionText.destroy(); gotItText.destroy(); instructionEarth.destroy(); instructionShip.destroy(); // Clean up instruction asteroids for (var i = 0; i < instructionAsteroids.length; i++) { instructionAsteroids[i].destroy(); } instructionAsteroids = []; instructionsVisible = false; // Initialize all game assets now initializeGameAssets(); // Re-define the game.down handler for normal gameplay } return; } // Check if any improve lasers text was clicked for (var k = 0; k < defensiveShips.length; k++) { var ship = defensiveShips[k]; if (ship.visible && ship.improveLasersText.visible) { // Convert coordinates to check if improve lasers text was clicked var improveLasersClickArea = { x: ship.improveLasersText.x - ship.improveLasersText.width, y: ship.improveLasersText.y - ship.improveLasersText.height / 2, width: ship.improveLasersText.width, height: ship.improveLasersText.height }; // Convert click coordinates to GUI space var guiPos = LK.gui.topRight.toLocal(game.toGlobal({ x: x, y: y })); if (guiPos.x >= improveLasersClickArea.x && guiPos.x <= improveLasersClickArea.x + improveLasersClickArea.width && guiPos.y >= improveLasersClickArea.y && guiPos.y <= improveLasersClickArea.y + improveLasersClickArea.height) { // Check if player has enough points to use improve lasers if (LK.getScore() < 75) { return; // Not enough points, don't process the upgrade } // Find all placed ships that don't already have improved lasers var upgradeableShips = []; for (var j = 0; j < defensiveShips.length; j++) { if (defensiveShips[j].placed && !defensiveShips[j].hasImprovedLasers) { upgradeableShips.push(defensiveShips[j]); } } // Randomly select one ship to upgrade if (upgradeableShips.length > 0) { // Deduct 75 points from score LK.setScore(LK.getScore() - 75); scoreTxt.setText('Score: ' + LK.getScore()); var randomIndex = Math.floor(Math.random() * upgradeableShips.length); var selectedShip = upgradeableShips[randomIndex]; selectedShip.hasImprovedLasers = true; // Visual feedback - flash the upgraded ship tween(selectedShip, { tint: 0x00ff00 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(selectedShip, { tint: 0xffffff }, { duration: 500, easing: tween.easeOut }); } }); } return; // Don't fire lasers when clicking improve lasers } } } // Check if laser firing is on cooldown if (laserCooldownActive) { return; } // Make all placed ships fire lasers at the clicked point for (var k = 0; k < defensiveShips.length; k++) { var ship = defensiveShips[k]; // Only fire from ships that are placed if (!ship.placed) { continue; } // Calculate direction from this ship to clicked position var dx = x - ship.x; var dy = y - ship.y; var distance = Math.sqrt(dx * dx + dy * dy); // Calculate rotation angle to face the target point var targetRotation = Math.atan2(dy, dx) + Math.PI / 2; // Add PI/2 since ship top should face target // Rotate the ship to face the target tween(ship, { rotation: targetRotation }, { duration: 200, easing: tween.easeOut }); var speed = 8; var normalizedDx = 0; var normalizedDy = 0; if (distance > 0) { normalizedDx = dx / distance; normalizedDy = dy / distance; } // Fire one or two lasers depending on ship upgrade if (ship.hasImprovedLasers) { // Fire two lasers with slight spread var spreadAngle = 0.1; // Radians for spread // First laser (slightly left) var laser1 = new Laser(); laser1.x = ship.x; laser1.y = ship.y; var angle1 = Math.atan2(normalizedDy, normalizedDx) - spreadAngle; laser1.velocityX = Math.cos(angle1) * speed; laser1.velocityY = Math.sin(angle1) * speed; lasers.push(laser1); game.addChild(laser1); // Second laser (slightly right) var laser2 = new Laser(); laser2.x = ship.x; laser2.y = ship.y; var angle2 = Math.atan2(normalizedDy, normalizedDx) + spreadAngle; laser2.velocityX = Math.cos(angle2) * speed; laser2.velocityY = Math.sin(angle2) * speed; lasers.push(laser2); game.addChild(laser2); } else { // Fire single laser var laser = new Laser(); laser.x = ship.x; laser.y = ship.y; laser.velocityX = normalizedDx * speed; laser.velocityY = normalizedDy * speed; lasers.push(laser); game.addChild(laser); } } // Start laser cooldown for 0.2 seconds laserCooldownActive = true; var cooldownTarget = {}; // Dummy object for tween tween(cooldownTarget, { dummy: 1 }, { duration: 200, onFinish: function onFinish() { laserCooldownActive = false; } }); }; // Define variables that will be initialized after instructions var sunX, sunY, sun, planets, mercury, venus, earth, mars, jupiter, saturn, uranus, neptune; var orbitLines, bullets, lasers, asteroids, asteroidSpawnTimer, lives; var scoreTxt, livesTxt, defensiveShips, selectedShipIndex, isDragging; var totalShips, availableShips, lastScoreCheck; var laserCooldownActive = false; // Function to initialize game assets function initializeGameAssets() { sunX = 2048 / 2; sunY = 2732 / 2; sun = game.addChild(LK.getAsset('sun', { anchorX: 0.5, anchorY: 0.5, x: sunX, y: sunY })); planets = []; mercury = new Planet(50, 0x8c7853, 150, 0.015); venus = new Planet(70, 0xffc649, 200, 0.012); earth = new Planet(80, 0x4169e1, 300, 0.008); mars = new Planet(60, 0xff4500, 450, 0.005); jupiter = new Planet(120, 0xd2691e, 600, 0.003); saturn = new Planet(100, 0xffd700, 750, 0.002); uranus = new Planet(90, 0x40e0d0, 900, 0.0015); neptune = new Planet(85, 0x0080ff, 1050, 0.001); planets.push(mercury); planets.push(venus); planets.push(earth); planets.push(mars); planets.push(jupiter); planets.push(saturn); planets.push(uranus); planets.push(neptune); // Create orbit lines for each planet orbitLines = []; var planetOrbits = [150, 200, 300, 450, 600, 750, 900, 1050]; // Mercury to Neptune orbit radii for (var i = 0; i < planetOrbits.length; i++) { var orbitLine = new OrbitLine(planetOrbits[i]); orbitLine.x = sunX; orbitLine.y = sunY; orbitLines.push(orbitLine); game.addChild(orbitLine); } for (var i = 0; i < planets.length; i++) { game.addChild(planets[i]); } bullets = []; lasers = []; asteroids = []; asteroidSpawnTimer = 0; lives = 4; scoreTxt = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.x = 0; LK.gui.top.addChild(scoreTxt); livesTxt = new Text2('Lives: 4', { size: 60, fill: 0xFFFFFF }); livesTxt.anchor.set(0.5, 0); livesTxt.x = 0; livesTxt.y = 70; LK.gui.top.addChild(livesTxt); defensiveShips = []; selectedShipIndex = -1; isDragging = false; totalShips = 4; // Maximum number of ships availableShips = 1; // Start with 1 ship available lastScoreCheck = 0; // Track score for adding new ships // Create 4 defensive ships but only show the available ones for (var i = 0; i < totalShips; i++) { var defensiveShip = LK.getAsset('defensiveShip', { anchorX: 0.5, anchorY: 0.5, x: -80, // Position all ships in the same spot in top right corner y: 80 }); defensiveShip.shipIndex = i; defensiveShip.placed = false; defensiveShip.selected = false; defensiveShip.requiresConfirmation = false; defensiveShip.hasImprovedLasers = false; // Only show ships that are available defensiveShip.visible = i < availableShips; defensiveShips.push(defensiveShip); LK.gui.topRight.addChild(defensiveShip); // Create "Improve Lasers" text for this ship var improveLasersText = new Text2('Improve Lasers', { size: 44, fill: 0xFFFFFF }); improveLasersText.anchor.set(1, 0.5); // Right anchor to position to left of ship improveLasersText.x = -140; // Position further to the left of the ship improveLasersText.y = 80; improveLasersText.visible = i < availableShips && LK.getScore() >= 75; defensiveShip.improveLasersText = improveLasersText; // Store reference on ship LK.gui.topRight.addChild(improveLasersText); // Create cost text below improve lasers var costText = new Text2('Cost: 75 Points', { size: 32, fill: 0xcccccc }); costText.anchor.set(1, 0.5); // Right anchor to position to left of ship costText.x = -140; // Position further to the left of the ship costText.y = 110; // Position below improve lasers text costText.visible = i < availableShips && LK.getScore() >= 75; defensiveShip.costText = costText; // Store reference on ship LK.gui.topRight.addChild(costText); } // Add down handler to each defensive ship for (var i = 0; i < defensiveShips.length; i++) { defensiveShips[i].down = function (x, y, obj) { var ship = this; var shipIndex = ship.shipIndex; // Only allow interaction with visible/available ships if (!ship.visible) { return; } if (ship.placed) { // Ship has been placed, allow selection for shooting // Deselect all other ships for (var j = 0; j < defensiveShips.length; j++) { if (j !== shipIndex && defensiveShips[j].selected) { defensiveShips[j].selected = false; tween(defensiveShips[j], { alpha: 1.0 }, { duration: 200 }); } } if (!ship.selected) { ship.selected = true; selectedShipIndex = shipIndex; tween(ship, { alpha: 0.7 }, { duration: 200 }); } // Removed else block to prevent manual dis-selection of placed ships return; } // Ship not placed yet - check if it needs confirmation or can start dragging if (!ship.requiresConfirmation) { // First click - select ship and require confirmation // Deselect all other ships for (var j = 0; j < defensiveShips.length; j++) { if (j !== shipIndex) { defensiveShips[j].selected = false; defensiveShips[j].requiresConfirmation = false; tween(defensiveShips[j], { alpha: 1.0 }, { duration: 200 }); } } // Select this ship and mark it as requiring confirmation ship.selected = true; ship.requiresConfirmation = true; selectedShipIndex = shipIndex; tween(ship, { alpha: 0.7 }, { duration: 200 }); } else { // Second click - start dragging isDragging = true; // Store original scale before moving var originalScaleX = ship.scaleX; var originalScaleY = ship.scaleY; // No need to shift ships since they're all in the same position // Move defensive ship to game area for dragging var gamePos = game.toLocal(LK.gui.topRight.toGlobal({ x: ship.x, y: ship.y })); LK.gui.topRight.removeChild(ship); game.addChild(ship); ship.x = gamePos.x; ship.y = gamePos.y; // Restore original scale after moving to game area ship.scaleX = originalScaleX; ship.scaleY = originalScaleY; } }; } } game.move = function (x, y, obj) { // Move ship to cursor position during dragging if (isDragging && selectedShipIndex >= 0) { var ship = defensiveShips[selectedShipIndex]; ship.x = x; ship.y = y; } }; game.up = function (x, y, obj) { if (isDragging && selectedShipIndex >= 0) { isDragging = false; // Defensive ship is now placed in the solar system var placedShip = defensiveShips[selectedShipIndex]; // Check if ship is off-screen and needs to be moved back to available ships area var shipHalfWidth = 40; // Half width of defensive ship (80/2) var shipHalfHeight = 55; // Half height of defensive ship (110/2) var isOffScreen = placedShip.x - shipHalfWidth < 0 || placedShip.x + shipHalfWidth > 2048 || placedShip.y - shipHalfHeight < 0 || placedShip.y + shipHalfHeight > 2732; if (isOffScreen) { // Move ship back to available ships area game.removeChild(placedShip); LK.gui.topRight.addChild(placedShip); // Place ship back at the single spawn position in top right corner placedShip.x = -80; placedShip.y = 80; placedShip.placed = false; } else { placedShip.placed = true; } placedShip.selected = false; selectedShipIndex = -1; tween(placedShip, { alpha: 1.0 }, { duration: 200 }); } }; game.update = function () { // Don't update game while instructions are visible if (instructionsVisible) { // Spawn asteroids for instruction demonstration instructionAsteroidSpawnTimer++; if (instructionAsteroidSpawnTimer > 90) { // Spawn every 1.5 seconds var asteroid = new Asteroid(); // Randomly choose left or bottom side to spawn from var spawnSide = Math.random() < 0.5 ? 'left' : 'bottom'; if (spawnSide === 'left') { // Spawn from left side at random Y position asteroid.x = -50; asteroid.y = Math.random() * 2732; } else { // Spawn from bottom side at random X position asteroid.x = Math.random() * 2048; asteroid.y = 2732 + 50; } // Calculate direction toward instruction earth var dx = instructionEarth.x - asteroid.x; var dy = instructionEarth.y - asteroid.y; var distance = Math.sqrt(dx * dx + dy * dy); var speed = 2; if (distance > 0) { asteroid.velocityX = dx / distance * speed; asteroid.velocityY = dy / distance * speed; } instructionAsteroids.push(asteroid); game.addChild(asteroid); instructionAsteroidSpawnTimer = 0; } // Count active instruction lasers var activeLasers = 0; for (var m = 0; m < instructionAsteroids.length; m++) { if (instructionAsteroids[m] instanceof Laser) { activeLasers++; } } // Auto-fire from instruction ship every 45 frames (0.75 seconds) - only if no active laser if (instructionAsteroidSpawnTimer % 45 === 0 && instructionAsteroids.length > 0 && activeLasers === 0) { // Find closest asteroid to instruction ship var closestAsteroid = null; var closestDistance = Infinity; for (var k = 0; k < instructionAsteroids.length; k++) { var asteroid = instructionAsteroids[k]; if (asteroid instanceof Asteroid) { var dx = asteroid.x - instructionShip.x; var dy = asteroid.y - instructionShip.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestAsteroid = asteroid; } } } // Fire laser at closest asteroid only if it's visible on screen and not targeting earth if (closestAsteroid && closestAsteroid.x >= -50 && closestAsteroid.x <= 2098 && closestAsteroid.y >= -50 && closestAsteroid.y <= 2782) { // Check if firing would hit the earth - don't fire if trajectory passes too close to earth var dx = closestAsteroid.x - instructionShip.x; var dy = closestAsteroid.y - instructionShip.y; var distance = Math.sqrt(dx * dx + dy * dy); // Calculate predicted asteroid position var laserSpeed = 8; var timeToTarget = distance / laserSpeed; var predictedX = closestAsteroid.x + closestAsteroid.velocityX * timeToTarget; var predictedY = closestAsteroid.y + closestAsteroid.velocityY * timeToTarget; // Check if laser trajectory would pass too close to earth var earthDx = instructionEarth.x - instructionShip.x; var earthDy = instructionEarth.y - instructionShip.y; var targetDx = predictedX - instructionShip.x; var targetDy = predictedY - instructionShip.y; // Calculate angle between earth direction and target direction var earthAngle = Math.atan2(earthDy, earthDx); var targetAngle = Math.atan2(targetDy, targetDx); var angleDiff = Math.abs(earthAngle - targetAngle); if (angleDiff > Math.PI) { angleDiff = 2 * Math.PI - angleDiff; } // Normalize to shortest angle // Only fire if angle difference is greater than 0.3 radians (~17 degrees) to avoid hitting earth if (angleDiff > 0.3) { var instructionLaser = new Laser(); instructionLaser.x = instructionShip.x; instructionLaser.y = instructionShip.y; // Calculate direction to predicted position var laserDx = predictedX - instructionLaser.x; var laserDy = predictedY - instructionLaser.y; var laserDistance = Math.sqrt(laserDx * laserDx + laserDy * laserDy); // Add aiming inaccuracy - larger error at longer distances var aimError = laserDistance / 300 * 0.15; // Reduced error for better accuracy var randomAngleOffset = (Math.random() - 0.5) * aimError; // Random offset between -aimError/2 and +aimError/2 var baseAngle = Math.atan2(laserDy, laserDx); var aimAngle = baseAngle + randomAngleOffset; var speed = 8; if (laserDistance > 0) { instructionLaser.velocityX = Math.cos(aimAngle) * speed; instructionLaser.velocityY = Math.sin(aimAngle) * speed; } // Rotate ship to face target (still accurate rotation for visual effect) var targetRotation = Math.atan2(laserDy, laserDx) + Math.PI / 2; tween(instructionShip, { rotation: targetRotation }, { duration: 200, easing: tween.easeOut }); instructionAsteroids.push(instructionLaser); // Reuse instructionAsteroids array for cleanup game.addChild(instructionLaser); } } } // Update instruction asteroids and lasers for (var i = instructionAsteroids.length - 1; i >= 0; i--) { var object = instructionAsteroids[i]; object.update(); // Check if it's a laser hitting an asteroid if (object instanceof Laser) { var laserHit = false; for (var j = instructionAsteroids.length - 1; j >= 0 && !laserHit; j--) { var target = instructionAsteroids[j]; if (target instanceof Asteroid && object.intersects(target)) { object.destroy(); instructionAsteroids.splice(i, 1); target.destroy(); instructionAsteroids.splice(j > i ? j - 1 : j, 1); laserHit = true; if (j < i) { i--; } // Adjust index since we removed an element before current break; } } // Remove laser if off-screen and not hit if (!laserHit && (object.x < -100 || object.x > 2148 || object.y < -100 || object.y > 2832)) { object.destroy(); instructionAsteroids.splice(i, 1); } } else if (object instanceof Asteroid) { // Remove asteroids that are off-screen or hit the earth if (object.x < -100 || object.x > 2148 || object.y < -100 || object.y > 2832) { object.destroy(); instructionAsteroids.splice(i, 1); } else { // Check if asteroid hits instruction earth (simple distance check) var dx = object.x - instructionEarth.x; var dy = object.y - instructionEarth.y; var distanceSquared = dx * dx + dy * dy; if (distanceSquared < 10000) { // Collision distance - flash earth dim red tween(instructionEarth, { tint: 0x664444 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(instructionEarth, { tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); object.destroy(); instructionAsteroids.splice(i, 1); } } } } return; } // Check if we should add a new ship (every 50 points up to 200, then every 100 points) var currentScore = LK.getScore(); var newAvailableShips; if (currentScore < 200) { // Every 50 points up to 200 newAvailableShips = Math.min(totalShips, 1 + Math.floor(currentScore / 50)); } else { // After 200: base ships from first 200 points plus additional ships every 100 points starting from 200 var baseShips = 1 + Math.floor(200 / 50); // Ships earned up to 200 points (5 total: 1 + 4) var additionalShips = Math.floor((currentScore - 200) / 100); // Additional ships every 100 points after 200 newAvailableShips = Math.min(totalShips, baseShips + additionalShips); } if (newAvailableShips > availableShips) { availableShips = newAvailableShips; // Make the newly available ship visible for (var k = 0; k < availableShips; k++) { if (!defensiveShips[k].visible) { defensiveShips[k].visible = true; defensiveShips[k].improveLasersText.visible = currentScore >= 75; defensiveShips[k].costText.visible = currentScore >= 75; } } } // Update improve lasers text visibility based on score (already using cached currentScore) for (var k = 0; k < availableShips; k++) { if (defensiveShips[k].visible) { defensiveShips[k].improveLasersText.visible = currentScore >= 75; defensiveShips[k].costText.visible = currentScore >= 75; } } for (var i = 0; i < planets.length; i++) { planets[i].update(); } // Check if at least one spaceship is placed before spawning asteroids var hasPlacedShip = false; for (var k = 0; k < defensiveShips.length; k++) { if (defensiveShips[k].placed) { hasPlacedShip = true; break; } } // Only spawn asteroids if a spaceship is placed if (hasPlacedShip) { asteroidSpawnTimer++; // Calculate spawn frequency based on score - gradual increase after score 50 var baseSpawnDelay = 120; var minSpawnDelay = 20; // Higher minimum for less dramatic increase var cachedScore = LK.getScore(); // Cache score to avoid multiple calls var currentSpawnDelay; if (cachedScore < 50) { // Normal progression before score 50 var scoreSpeedUp = Math.floor(cachedScore / 100); currentSpawnDelay = Math.max(60, baseSpawnDelay - scoreSpeedUp * 10); } else { // Gradual increase after score 50 - slower progression var excessScore = cachedScore - 50; var linearSpeedUp = Math.floor(excessScore / 25); // Reduced frequency: every 25 points instead of 10 currentSpawnDelay = Math.max(minSpawnDelay, 60 - linearSpeedUp * 1); // Smaller reduction: 1 frame instead of 2 } if (asteroidSpawnTimer > currentSpawnDelay) { var asteroid = new Asteroid(); // Spawn only from bottom and left sides (angles between PI and 2*PI) var spawnAngle = Math.PI + Math.random() * Math.PI; var spawnDistance = 1500; var cosSpawn = Math.cos(spawnAngle); var sinSpawn = Math.sin(spawnAngle); asteroid.x = sunX + cosSpawn * spawnDistance; asteroid.y = sunY + sinSpawn * spawnDistance; // Set initial velocity toward Earth's current position var dx = earth.x - asteroid.x; var dy = earth.y - asteroid.y; var distanceSquared = dx * dx + dy * dy; if (distanceSquared > 0) { var distance = Math.sqrt(distanceSquared); // Increase speed based on score after reaching 50 points - much more gradual var baseSpeed = 2; var speedMultiplier = 1; if (cachedScore >= 50) { // Very gradual speed increase: 0.2% per point after 50, capped at 2x speed var speedIncrease = (cachedScore - 50) * 0.002; // Reduced from 0.02 to 0.002 speedMultiplier = Math.min(2.0, 1 + speedIncrease); // Cap at 2x speed (reached at score 550) } var speed = baseSpeed * speedMultiplier / distance; // Cache division asteroid.velocityX = dx * speed; asteroid.velocityY = dy * speed; } asteroids.push(asteroid); game.addChild(asteroid); asteroidSpawnTimer = 0; } } for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); bullets.splice(i, 1); continue; } for (var j = asteroids.length - 1; j >= 0; j--) { if (bullet.intersects(asteroids[j])) { LK.setScore(LK.getScore() + 5); scoreTxt.setText('Score: ' + LK.getScore()); bullet.destroy(); bullets.splice(i, 1); asteroids[j].destroy(); asteroids.splice(j, 1); break; } } } // Update lasers for (var i = lasers.length - 1; i >= 0; i--) { var laser = lasers[i]; laser.update(); if (laser.x < -50 || laser.x > 2098 || laser.y < -50 || laser.y > 2782) { laser.destroy(); lasers.splice(i, 1); continue; } // Check laser collision with asteroids var laserHit = false; for (var j = asteroids.length - 1; j >= 0 && !laserHit; j--) { var asteroid = asteroids[j]; // Quick distance check before expensive intersects call var dx = laser.x - asteroid.x; var dy = laser.y - asteroid.y; var distanceSquared = dx * dx + dy * dy; if (distanceSquared < 900 && laser.intersects(asteroid)) { // 30*30 rough collision area LK.setScore(LK.getScore() + 5); scoreTxt.setText('Score: ' + LK.getScore()); laser.destroy(); lasers.splice(i, 1); asteroid.destroy(); asteroids.splice(j, 1); laserHit = true; break; } } } for (var i = asteroids.length - 1; i >= 0; i--) { var asteroid = asteroids[i]; asteroid.update(); var asteroidHit = false; // Cache asteroid position relative to sun var dx = asteroid.x - sunX; var dy = asteroid.y - sunY; var sunDistanceSquared = dx * dx + dy * dy; // Check sun collision first (most common) if (sunDistanceSquared < 14400) { // 120 * 120 = 14400 asteroid.destroy(); asteroids.splice(i, 1); continue; } // Early exit if asteroid is far from all planets (optimization) var minPlanetDistance = 200; // Approximate max planet radius + safety margin if (sunDistanceSquared > 1440000) { // 1200 * 1200 - beyond Neptune's orbit continue; } // Count placed ships to determine if immunity should apply var placedShipsCount = 0; for (var m = 0; m < defensiveShips.length; m++) { if (defensiveShips[m].placed) { placedShipsCount++; } } // Check asteroid collision with defensive ships first (only if more than one ship is placed) if (placedShipsCount > 1) { for (var k = 0; k < defensiveShips.length && !asteroidHit; k++) { var ship = defensiveShips[k]; if (ship.placed && asteroid.intersects(ship)) { // Flash ship dim red tween(ship, { tint: 0x664444 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(ship, { tint: 0xFFFFFF }, { duration: 300, easing: tween.easeOut }); } }); // Remove the ship ship.destroy(); defensiveShips.splice(k, 1); // Adjust availableShips count if (availableShips > defensiveShips.length) { availableShips = defensiveShips.length; } asteroid.destroy(); asteroids.splice(i, 1); asteroidHit = true; break; } } } // Only check planet collisions if not destroyed by sun or ships for (var j = 0; j < planets.length && !asteroidHit; j++) { var planet = planets[j]; // Quick distance check before expensive intersects call var planetDx = asteroid.x - planet.x; var planetDy = asteroid.y - planet.y; var planetDistanceSquared = planetDx * planetDx + planetDy * planetDy; if (planetDistanceSquared < 10000 && asteroid.intersects(planet)) { // 100*100 rough collision area if (planet === earth) { LK.effects.flashScreen(0x440000, 1000); lives--; livesTxt.setText('Lives: ' + lives); if (lives <= 0) { LK.showGameOver(); return; } } asteroid.destroy(); asteroids.splice(i, 1); asteroidHit = true; break; } } } };
===================================================================
--- original.js
+++ change.js
@@ -135,9 +135,9 @@
/****
* Game Code
****/
// Show instructions before game starts
-var instructionText = new Text2(" How to play:\n\nGoal:\n- protect the Earth from asteroid collisions\n- you will be given a spaceship that shoots lasers\n- you will use these lasers to destroy asteroids\n- if the Earth gets hit with 4 asteroids, you lose\n- if you have multiple spaceships, they will all fire where you choose\n\nPoints:\n- every asteroid you destroy will earn you five points\n- every 50 points, you will recieve a new spaceship you can put in the solar system\n- if you reach 200 points, that interval will increase to every 100 points\n- with a price of 75 points, you can buy a laser upgrade that randomly applies to one ship in play, giving it the ability to shoot two lasers instead of one\n\nAsteroids:\n- asteroids are your enimies\n- they can be destroyed with one laser hit\n- they will come from random directions, so be aware of all sides of the screen\n- planets are you friends, all planets other than Earth deflect asteroids\n\nControls:\n- select a spaceship until it shrinks, then click and drag it to move it, release to place it\n- click any point on the sreen to fire lasers in that direction\n- if you have multiple spaceships, they will all fire where you choose", {
+var instructionText = new Text2(" How to play:\n\nGoal:\n- protect the Earth from asteroid collisions\n- you will be given a spaceship that shoots lasers\n- you will use these lasers to destroy asteroids\n- if the Earth gets hit with 4 asteroids, you lose\n- if you have multiple spaceships, they will all fire where you choose\n\nPoints:\n- every asteroid you destroy will earn you five points\n- every 50 points, you will recieve a new spaceship you can put in the solar system\n- if you reach 200 points, that interval will increase to every 100 points\n- with a price of 75 points, you can buy a laser upgrade that randomly applies to one ship in play, giving it the ability to shoot two lasers instead of one\n\nAsteroids:\n- asteroids are your enimies\n- they can be destroyed with one laser hit\n- they will come from random directions, so be aware of all sides of the screen\n- planets are you friends, all planets other than Earth deflect asteroids\n- if a ship gets hit with an asteroid, it will be removed, so keep a lookout for your ships\n\nControls:\n- select a spaceship until it shrinks, then click and drag it to move it, release to place it\n- click any point on the sreen to fire lasers in that direction\n- if you have multiple spaceships, they will all fire where you choose", {
size: 60,
fill: 0xFFFFFF,
wordWrap: true,
wordWrapWidth: 1600