/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
shieldLevel: 1,
laserLevel: 1,
thrusterLevel: 1
});
/****
* Classes
****/
var Asteroid = Container.expand(function () {
var self = Container.call(this);
// Initialize with random size
self.size = Math.random() * 0.5 + 0.8; // Between 0.8 and 1.3
self.health = Math.ceil(self.size * 3);
self.initialHealth = self.health;
self.speedX = (Math.random() - 0.5) * 4;
self.speedY = Math.random() * 3 + 2;
self.rotationSpeed = (Math.random() - 0.5) * 0.05;
self.value = Math.ceil(self.size * 10); // Points value
self.resourceValue = Math.ceil(self.size * 2); // Resource value
var asteroidGraphic = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.size,
scaleY: self.size
});
self.takeDamage = function (amount) {
self.health -= amount;
// Visual feedback
LK.effects.flashObject(self, 0xffffff, 200);
// Break apart
if (self.health <= 0) {
self["break"]();
return true;
}
// Change appearance based on damage
var healthPercent = self.health / self.initialHealth;
asteroidGraphic.alpha = 0.5 + healthPercent * 0.5;
return false;
};
self["break"] = function () {
// Create minerals
var mineralCount = Math.ceil(self.size * 2);
for (var i = 0; i < mineralCount; i++) {
var mineral = new Mineral();
mineral.x = self.x + (Math.random() - 0.5) * 50;
mineral.y = self.y + (Math.random() - 0.5) * 50;
minerals.push(mineral);
game.addChild(mineral);
}
// Add score
addScore(self.value);
// Mark for removal
self.toBeRemoved = true;
};
self.update = function () {
// Move asteroid
self.x += self.speedX;
self.y += self.speedY;
// Rotate asteroid
asteroidGraphic.rotation += self.rotationSpeed;
// Wrap around screen edges horizontally
if (self.x < -100) {
self.x = 2148;
}
if (self.x > 2148) {
self.x = -100;
}
// Remove if off bottom of screen
if (self.y > 2832) {
self.toBeRemoved = true;
}
};
return self;
});
var ExplosiveAsteroid = Asteroid.expand(function () {
var self = Asteroid.call(this);
// Override the asteroid graphic with an explosive one
self.removeChildren();
var asteroidGraphic = self.attachAsset('explosiveAsteroid', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: self.size,
scaleY: self.size
});
// Make it pulse
function pulse() {
tween(asteroidGraphic, {
alpha: 0.6
}, {
duration: 500,
onFinish: function onFinish() {
tween(asteroidGraphic, {
alpha: 1
}, {
duration: 500,
onFinish: pulse
});
}
});
}
pulse();
// Override break function to create explosion
var originalBreak = self["break"];
self["break"] = function () {
// Create explosion
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
explosions.push(explosion);
game.addChild(explosion);
// Original break functionality
originalBreak();
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphic = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.radius = 50;
self.damage = 40;
self.lifetime = 500; // milliseconds
self.born = Date.now();
// Play explosion sound
LK.getSound('explosion').play();
// Animate explosion
tween(explosionGraphic, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: self.lifetime,
onFinish: function onFinish() {
self.toBeRemoved = true;
}
});
self.update = function () {
self.radius = 50 + (Date.now() - self.born) / self.lifetime * 100;
};
return self;
});
var GravitationalAnomaly = Container.expand(function () {
var self = Container.call(this);
var anomalyGraphic = self.attachAsset('anomaly', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.radius = 150;
self.strength = 0.5;
self.update = function () {
// Visual effect or animation can be added here
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphic = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.power = 1; // Will be set by ship when fired
self.update = function () {
self.y -= self.speed;
// Destroy when off screen
if (self.y < -100) {
self.toBeRemoved = true;
}
};
return self;
});
var Mineral = Container.expand(function () {
var self = Container.call(this);
var mineralGraphic = self.attachAsset('mineral', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = (Math.random() - 0.5) * 2;
self.speedY = Math.random() * 2 + 1;
self.value = Math.floor(Math.random() * 3) + 1;
self.rotationSpeed = (Math.random() - 0.5) * 0.1;
// Different colors based on value
if (self.value === 1) {
mineralGraphic.tint = 0x95a5a6; // Iron (gray)
} else if (self.value === 2) {
mineralGraphic.tint = 0xf1c40f; // Gold (yellow)
} else {
mineralGraphic.tint = 0x1abc9c; // Platinum (teal)
}
self.update = function () {
// Move mineral
self.x += self.speedX;
self.y += self.speedY;
// Rotate mineral
mineralGraphic.rotation += self.rotationSpeed;
// Wrap around screen edges horizontally
if (self.x < -50) {
self.x = 2098;
}
if (self.x > 2098) {
self.x = -50;
}
// Remove if off bottom of screen
if (self.y > 2832) {
self.toBeRemoved = true;
}
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
// Ship attributes
self.maxShields = 100;
self.shields = self.maxShields;
self.speed = 5;
self.lastFired = 0;
self.fireRate = 500; // milliseconds between shots
self.laserPower = 1;
self.invulnerable = false;
// Create ship body
var shipBody = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5
});
// Create shield indicator
var shieldIndicator = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
// Method to update shield appearance
self.updateShieldDisplay = function () {
var shieldPercent = self.shields / self.maxShields;
shieldIndicator.alpha = 0.1 + shieldPercent * 0.4;
if (self.shields < 30) {
shieldIndicator.tint = 0xff0000; // Red when low
} else if (self.shields < 60) {
shieldIndicator.tint = 0xffff00; // Yellow when medium
} else {
shieldIndicator.tint = 0x3498db; // Blue when high
}
};
// Method to take damage
self.takeDamage = function (amount) {
if (self.invulnerable) {
return;
}
self.shields -= amount;
LK.getSound('damage').play();
// Visual feedback
LK.effects.flashObject(self, 0xff0000, 500);
// Make invulnerable briefly
self.invulnerable = true;
LK.setTimeout(function () {
self.invulnerable = false;
}, 1000);
self.updateShieldDisplay();
if (self.shields <= 0) {
gameOver();
}
};
// Method to fire laser
self.fireLaser = function () {
var now = Date.now();
if (now - self.lastFired < self.fireRate) {
return;
}
self.lastFired = now;
var laser = new Laser();
laser.x = self.x;
laser.y = self.y - 50;
laser.power = self.laserPower;
lasers.push(laser);
game.addChild(laser);
LK.getSound('laser').play();
};
// Init shield display
self.updateShieldDisplay();
return self;
});
var UpgradeCrate = Container.expand(function () {
var self = Container.call(this);
var crateGraphic = self.attachAsset('upgradeCrate', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedY = 3;
self.pulseAmount = 0;
// Pulse effect
function pulse() {
tween(crateGraphic, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.sinOut,
onFinish: function onFinish() {
tween(crateGraphic, {
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.sinIn,
onFinish: pulse
});
}
});
}
pulse();
self.update = function () {
// Move crate
self.y += self.speedY;
// Remove if off bottom of screen
if (self.y > 2832) {
self.toBeRemoved = true;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var score = 0;
var resources = 0;
var level = 1;
var ship;
var lasers = [];
var asteroids = [];
var explosiveAsteroids = [];
var minerals = [];
var explosions = [];
var upgradeCrates = [];
var lastAsteroidTime = 0;
var gravitationalAnomalies = [];
var asteroidSpawnRate = 1500; // milliseconds between asteroid spawns
var nextUpgradeScore = 500;
var gameActive = true;
var dragOffset = {
x: 0,
y: 0
};
var dragActive = false;
// Initialize background
game.setBackgroundColor(0x000033);
// Create UI elements
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -300;
scoreText.y = 20;
var resourceText = new Text2('Resources: 0', {
size: 60,
fill: 0xFFFFFF
});
resourceText.anchor.set(0, 0);
LK.gui.topRight.addChild(resourceText);
resourceText.x = -300;
resourceText.y = 90;
var levelText = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
LK.gui.topRight.addChild(levelText);
levelText.x = -300;
levelText.y = 160;
var shieldText = new Text2('Shield: 100%', {
size: 60,
fill: 0xFFFFFF
});
shieldText.anchor.set(0, 0);
LK.gui.bottom.addChild(shieldText);
shieldText.x = -650;
shieldText.y = -80;
// Initialize ship
ship = new Ship();
ship.x = 2048 / 2;
ship.y = 2500;
game.addChild(ship);
// Load saved upgrades
loadUpgrades();
// Start background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.4,
duration: 1000
}
});
// Game functions
function addScore(points) {
score += points;
scoreText.setText('Score: ' + score);
// Check if player reached next upgrade threshold
if (score >= nextUpgradeScore) {
spawnUpgradeCrate();
nextUpgradeScore += 500;
}
// Check for level increase
var newLevel = Math.floor(score / 1000) + 1;
if (newLevel > level) {
level = newLevel;
levelText.setText('Level: ' + level);
// Increase difficulty
asteroidSpawnRate = Math.max(300, 1500 - level * 100);
}
}
function addResource(amount) {
resources += amount;
resourceText.setText('Resources: ' + resources);
// Save high score if better than previous
if (score > storage.highScore) {
storage.highScore = score;
}
}
function spawnAsteroid() {
// Decide whether to spawn regular or explosive asteroid
var isExplosive = Math.random() < 0.2;
var asteroid;
if (isExplosive) {
asteroid = new ExplosiveAsteroid();
explosiveAsteroids.push(asteroid);
} else {
asteroid = new Asteroid();
asteroids.push(asteroid);
}
// Position at random location at top of screen
asteroid.x = Math.random() * 2048;
asteroid.y = -100;
// Add to game
game.addChild(asteroid);
}
function spawnUpgradeCrate() {
var crate = new UpgradeCrate();
crate.x = Math.random() * (2048 - 200) + 100; // Keep away from edges
crate.y = -100;
upgradeCrates.push(crate);
game.addChild(crate);
}
function applyUpgrade() {
// Show upgrade options in a future version
// For now, just upgrade shields
if (resources >= 10) {
resources -= 10;
resourceText.setText('Resources: ' + resources);
// Upgrade a random system
var system = Math.floor(Math.random() * 3);
if (system === 0 && storage.shieldLevel < 5) {
storage.shieldLevel++;
ship.maxShields = 100 + (storage.shieldLevel - 1) * 25;
ship.shields = ship.maxShields;
shieldText.setText('Shield: ' + Math.floor(ship.shields) + '%');
ship.updateShieldDisplay();
} else if (system === 1 && storage.laserLevel < 5) {
storage.laserLevel++;
ship.laserPower = storage.laserLevel;
ship.fireRate = 500 - (storage.laserLevel - 1) * 50;
} else if (storage.thrusterLevel < 5) {
storage.thrusterLevel++;
ship.speed = 5 + (storage.thrusterLevel - 1);
}
LK.getSound('upgrade').play();
// Visual feedback
LK.effects.flashObject(ship, 0x9b59b6, 1000);
}
}
function loadUpgrades() {
// Apply saved upgrade levels
ship.maxShields = 100 + (storage.shieldLevel - 1) * 25;
ship.shields = ship.maxShields;
ship.laserPower = storage.laserLevel;
ship.fireRate = 500 - (storage.laserLevel - 1) * 50;
ship.speed = 5 + (storage.thrusterLevel - 1);
shieldText.setText('Shield: ' + Math.floor(ship.shields) + '%');
ship.updateShieldDisplay();
}
function gameOver() {
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
// Input handlers
game.down = function (x, y, obj) {
if (!gameActive) {
return;
}
// Start dragging the ship
dragOffset.x = ship.x - x;
dragOffset.y = ship.y - y;
dragActive = true;
// Fire laser on tap
ship.fireLaser();
};
game.move = function (x, y, obj) {
if (!gameActive || !dragActive) {
return;
}
// Move ship with drag, keeping it on screen
ship.x = Math.min(Math.max(x + dragOffset.x, 50), 2048 - 50);
ship.y = Math.min(Math.max(y + dragOffset.y, 50), 2732 - 50);
};
game.up = function (x, y, obj) {
dragActive = false;
};
// Game loop
game.update = function () {
if (!gameActive) {
return;
}
// Spawn new asteroids
var now = Date.now();
if (now - lastAsteroidTime > asteroidSpawnRate) {
spawnAsteroid();
lastAsteroidTime = now;
}
// Randomly spawn gravitational anomalies
if (Math.random() < 0.001) {
// Adjust probability as needed
var anomaly = new GravitationalAnomaly();
anomaly.x = Math.random() * 2048;
anomaly.y = Math.random() * 2732;
gravitationalAnomalies.push(anomaly);
game.addChild(anomaly);
}
// Update UI
shieldText.setText('Shield: ' + Math.floor(ship.shields) + '%');
// Update and check lasers
for (var i = lasers.length - 1; i >= 0; i--) {
var laser = lasers[i];
if (laser.toBeRemoved) {
game.removeChild(laser);
lasers.splice(i, 1);
continue;
}
// Check laser collisions with asteroids
for (var j = asteroids.length - 1; j >= 0; j--) {
var asteroid = asteroids[j];
if (laser.intersects(asteroid)) {
if (asteroid.takeDamage(laser.power)) {
// Asteroid was destroyed
game.removeChild(asteroid);
asteroids.splice(j, 1);
}
// Remove laser on hit
laser.toBeRemoved = true;
break;
}
}
// Check laser collisions with explosive asteroids
for (var j = explosiveAsteroids.length - 1; j >= 0; j--) {
var expAsteroid = explosiveAsteroids[j];
if (laser.intersects(expAsteroid)) {
if (expAsteroid.takeDamage(laser.power)) {
// Asteroid was destroyed
game.removeChild(expAsteroid);
explosiveAsteroids.splice(j, 1);
}
// Remove laser on hit
laser.toBeRemoved = true;
break;
}
}
}
// Update and check minerals
for (var i = minerals.length - 1; i >= 0; i--) {
var mineral = minerals[i];
if (mineral.toBeRemoved) {
game.removeChild(mineral);
minerals.splice(i, 1);
continue;
}
// Check if ship collects mineral
if (ship.intersects(mineral)) {
addResource(mineral.value);
LK.getSound('collect').play();
mineral.toBeRemoved = true;
// Visual feedback
LK.effects.flashObject(ship, 0x2ecc71, 200);
}
}
// Update and check asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
if (asteroid.toBeRemoved) {
game.removeChild(asteroid);
asteroids.splice(i, 1);
continue;
}
// Check collision with ship
if (ship.intersects(asteroid)) {
ship.takeDamage(10 + level);
asteroid["break"]();
game.removeChild(asteroid);
asteroids.splice(i, 1);
}
}
// Update and check explosive asteroids
for (var i = explosiveAsteroids.length - 1; i >= 0; i--) {
var expAsteroid = explosiveAsteroids[i];
if (expAsteroid.toBeRemoved) {
game.removeChild(expAsteroid);
explosiveAsteroids.splice(i, 1);
continue;
}
// Check collision with ship
if (ship.intersects(expAsteroid)) {
ship.takeDamage(20 + level * 2);
expAsteroid["break"]();
game.removeChild(expAsteroid);
explosiveAsteroids.splice(i, 1);
}
}
// Update and check explosions
for (var i = explosions.length - 1; i >= 0; i--) {
var explosion = explosions[i];
if (explosion.toBeRemoved) {
game.removeChild(explosion);
explosions.splice(i, 1);
continue;
}
// Check if ship is caught in explosion
var dx = ship.x - explosion.x;
var dy = ship.y - explosion.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < explosion.radius + 50) {
// Add ship radius
// Damage diminishes with distance
var damageMultiplier = 1 - distance / (explosion.radius + 50);
ship.takeDamage(explosion.damage * damageMultiplier);
}
}
// Update and check gravitational anomalies
for (var i = gravitationalAnomalies.length - 1; i >= 0; i--) {
var anomaly = gravitationalAnomalies[i];
if (anomaly.toBeRemoved) {
game.removeChild(anomaly);
gravitationalAnomalies.splice(i, 1);
continue;
}
// Check if ship is affected by anomaly
var dx = ship.x - anomaly.x;
var dy = ship.y - anomaly.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < anomaly.radius) {
// Apply gravitational pull
var pullStrength = anomaly.strength * (1 - distance / anomaly.radius);
ship.x += dx * pullStrength;
ship.y += dy * pullStrength;
}
}
// Update and check upgrade crates
for (var i = upgradeCrates.length - 1; i >= 0; i--) {
var crate = upgradeCrates[i];
if (crate.toBeRemoved) {
game.removeChild(crate);
upgradeCrates.splice(i, 1);
continue;
}
// Check if ship collects upgrade
if (ship.intersects(crate)) {
applyUpgrade();
crate.toBeRemoved = true;
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -147,8 +147,22 @@
self.radius = 50 + (Date.now() - self.born) / self.lifetime * 100;
};
return self;
});
+var GravitationalAnomaly = Container.expand(function () {
+ var self = Container.call(this);
+ var anomalyGraphic = self.attachAsset('anomaly', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.7
+ });
+ self.radius = 150;
+ self.strength = 0.5;
+ self.update = function () {
+ // Visual effect or animation can be added here
+ };
+ return self;
+});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphic = self.attachAsset('laser', {
anchorX: 0.5,
@@ -335,8 +349,9 @@
var minerals = [];
var explosions = [];
var upgradeCrates = [];
var lastAsteroidTime = 0;
+var gravitationalAnomalies = [];
var asteroidSpawnRate = 1500; // milliseconds between asteroid spawns
var nextUpgradeScore = 500;
var gameActive = true;
var dragOffset = {
@@ -521,8 +536,17 @@
if (now - lastAsteroidTime > asteroidSpawnRate) {
spawnAsteroid();
lastAsteroidTime = now;
}
+ // Randomly spawn gravitational anomalies
+ if (Math.random() < 0.001) {
+ // Adjust probability as needed
+ var anomaly = new GravitationalAnomaly();
+ anomaly.x = Math.random() * 2048;
+ anomaly.y = Math.random() * 2732;
+ gravitationalAnomalies.push(anomaly);
+ game.addChild(anomaly);
+ }
// Update UI
shieldText.setText('Shield: ' + Math.floor(ship.shields) + '%');
// Update and check lasers
for (var i = lasers.length - 1; i >= 0; i--) {
@@ -628,8 +652,27 @@
var damageMultiplier = 1 - distance / (explosion.radius + 50);
ship.takeDamage(explosion.damage * damageMultiplier);
}
}
+ // Update and check gravitational anomalies
+ for (var i = gravitationalAnomalies.length - 1; i >= 0; i--) {
+ var anomaly = gravitationalAnomalies[i];
+ if (anomaly.toBeRemoved) {
+ game.removeChild(anomaly);
+ gravitationalAnomalies.splice(i, 1);
+ continue;
+ }
+ // Check if ship is affected by anomaly
+ var dx = ship.x - anomaly.x;
+ var dy = ship.y - anomaly.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < anomaly.radius) {
+ // Apply gravitational pull
+ var pullStrength = anomaly.strength * (1 - distance / anomaly.radius);
+ ship.x += dx * pullStrength;
+ ship.y += dy * pullStrength;
+ }
+ }
// Update and check upgrade crates
for (var i = upgradeCrates.length - 1; i >= 0; i--) {
var crate = upgradeCrates[i];
if (crate.toBeRemoved) {