User prompt
Make the improve lasers button only be able to be used if the player has a score of at least 75 points. If used, remove 75 points from the players score. Put a “cost” in smaller text below the improve lasers text
Code edit (2 edits merged)
Please save this source code
User prompt
Change the change of the ship interval from a score of 350 to a score of 200
User prompt
Make the increase in speed a lot more spread out
User prompt
Change laser cooldown from 0.5 seconds to 0.2 seconds
User prompt
Increase size of asteroids
User prompt
Add a 0.5 second cooldown between each laser fire ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Reduce lag if possible
User prompt
If “improve lasers” is clicked, randomly assign a ship currently on the solar system the ability to shoot two lasers instead of one
User prompt
Change improve lasers font size to 44 and move it slightly to the left so it doesn’t overlap with the available ship
User prompt
Hide the improve lasers text only until the player’s score reaches 50
User prompt
Change improve lasers font size to 48
User prompt
For every available ship, put text that says “Improve Lasers” to the left of them. Font size 55
User prompt
Remove everything regarding improved lasers
User prompt
Put the improve lasers text to the left of the available ships
Code edit (1 edits merged)
Please save this source code
User prompt
Do not require a click to begin firing. Assume it is already selected
User prompt
When an available ship is selected, require it must be selected again before it is moved
User prompt
Make the frequency increase of spawning asteroids less dramatic and make it a slower increase
User prompt
Do show improve lasers text for every ship after the default ship
User prompt
Do not include improve lasers text for the first ship
User prompt
Below the available defensive ships after the first, add text that says “Improve Lasers”.
User prompt
After the player reaches 50 points, start increasing the speed of the asteroids
User prompt
Please fix the issue preventing asteroids from spawning on the instructions page.
User prompt
Still spawn asteroids from left and bottom of screen on instruction page and automate defensive ship next to spinning earth to shoot asteroids
/****
* 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
});
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 === 0x4169e1 && size === 85) {
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 350 points, that interval will increase to every 100 points\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\nControls:\n- select a spaceship, 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 - 300; // 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;
}
// 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;
}
var laser = new Laser();
laser.x = ship.x;
laser.y = ship.y;
// Calculate direction from this ship to clicked position
var dx = x - laser.x;
var dy = y - laser.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;
if (distance > 0) {
laser.velocityX = dx / distance * speed;
laser.velocityY = dy / distance * speed;
}
lasers.push(laser);
game.addChild(laser);
}
};
// 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;
// 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, 0x4169e1, 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;
// Only show ships that are available
defensiveShip.visible = i < availableShips;
defensiveShips.push(defensiveShip);
LK.gui.topRight.addChild(defensiveShip);
}
// Add "Improve Lasers" text to the left of ships (excluding the first one)
for (var k = 1; k < totalShips; k++) {
var improveLasersText = new Text2("Improve Lasers", {
size: 40,
fill: 0xFFFFFF
});
improveLasersText.anchor.set(1, 0.5); // Anchor to right side of text, middle vertically
improveLasersText.x = -100; // Position to the left of ships
improveLasersText.y = 80; // Same Y position as ships
improveLasersText.visible = k < availableShips; // Only show for available ships
LK.gui.topRight.addChild(improveLasersText);
}
// 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 350, then every 100 points)
var currentScore = LK.getScore();
var newAvailableShips;
if (currentScore <= 350) {
// Every 50 points up to 350
newAvailableShips = Math.min(totalShips, 1 + Math.floor(currentScore / 50));
} else {
// After 350: base ships from first 350 points (1 + 7 = 8) plus additional ships every 100 points
var baseShips = 1 + Math.floor(350 / 50); // Ships earned up to 350 points
var additionalShips = Math.floor((currentScore - 350) / 100); // Additional ships after 350
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;
}
}
// Update "Improve Lasers" text visibility for newly available ships
var improveLasersTexts = LK.gui.topRight.children.filter(function (child) {
return child instanceof Text2 && child.text === "Improve Lasers";
});
for (var k = 0; k < improveLasersTexts.length; k++) {
improveLasersTexts[k].visible = k + 1 < availableShips;
}
}
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
var baseSpeed = 2;
var speedMultiplier = cachedScore >= 50 ? 1 + (cachedScore - 50) * 0.02 : 1;
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--) {
if (laser.intersects(asteroids[j])) {
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
laser.destroy();
lasers.splice(i, 1);
asteroids[j].destroy();
asteroids.splice(j, 1);
laserHit = true;
break;
}
}
}
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
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;
}
// Only check planet collisions if not destroyed by sun
for (var j = 0; j < planets.length && !asteroidHit; j++) {
if (asteroid.intersects(planets[j])) {
if (planets[j] === 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
@@ -130,9 +130,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 350 points, that interval will increase to every 100 points\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\nControls:\n- select a spaceship, then click and drag it to move 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 350 points, that interval will increase to every 100 points\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\nControls:\n- select a spaceship, 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
@@ -336,17 +336,17 @@
defensiveShip.visible = i < availableShips;
defensiveShips.push(defensiveShip);
LK.gui.topRight.addChild(defensiveShip);
}
- // Add "Improve Lasers" text below ships (excluding the first one)
+ // Add "Improve Lasers" text to the left of ships (excluding the first one)
for (var k = 1; k < totalShips; k++) {
var improveLasersText = new Text2("Improve Lasers", {
size: 40,
fill: 0xFFFFFF
});
- improveLasersText.anchor.set(0.5, 0);
- improveLasersText.x = -80;
- improveLasersText.y = 150;
+ improveLasersText.anchor.set(1, 0.5); // Anchor to right side of text, middle vertically
+ improveLasersText.x = -100; // Position to the left of ships
+ improveLasersText.y = 80; // Same Y position as ships
improveLasersText.visible = k < availableShips; // Only show for available ships
LK.gui.topRight.addChild(improveLasersText);
}
// Add down handler to each defensive ship