/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var CosmicObject = Container.expand(function (type, speed, pointValue) {
var self = Container.call(this);
// Set default values if not provided
self.type = type || 'cosmicGem';
self.speed = speed || 2;
self.pointValue = pointValue || 1;
// Create the cosmic object visual
var objectGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
// Apply random rotation for visual interest
objectGraphics.rotation = Math.random() * Math.PI * 2;
// Define movement properties
self.velocityX = 0;
self.velocityY = self.speed;
self.beingPulled = false;
self.captureProgress = 0; // 0 to 1, where 1 means captured
// Update method called every tick
self.update = function () {
if (!self.beingPulled) {
// Normal movement
self.x += self.velocityX;
self.y += self.velocityY;
}
};
// Apply gravitational pull from the well
self.applyGravity = function (well, deltaTime) {
if (!well.active) {
return;
}
// Calculate distance between object and gravity well
var dx = well.x - self.x;
var dy = well.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Only apply gravity if within the well's influence
if (distance < well.radius) {
self.beingPulled = true;
// Calculate pull strength based on distance and well power
var pullStrength = Math.min(0.1, (well.radius - distance) / well.radius * 0.2) * well.power;
// Apply gravitational pull
self.velocityX += dx * pullStrength;
self.velocityY += dy * pullStrength;
// Apply velocity with damping for stability
self.x += self.velocityX * deltaTime;
self.y += self.velocityY * deltaTime;
// Increase capture progress when very close to the well
if (distance < well.radius * 0.2) {
self.captureProgress += 0.03;
// Visual feedback - scale down as being captured
objectGraphics.scale.x = objectGraphics.scale.y = 1 - self.captureProgress * 0.2;
// Object is fully captured
if (self.captureProgress >= 1) {
return true; // Signal that object is captured
}
}
} else {
self.beingPulled = false;
}
return false; // Not captured yet
};
return self;
});
var GravityWell = Container.expand(function () {
var self = Container.call(this);
// Create the gravity well visuals
var wellGraphics = self.attachAsset('gravityWell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Create the core of the gravity well
var coreGraphics = self.attachAsset('wellCore', {
anchorX: 0.5,
anchorY: 0.5
});
self.power = 1; // Base gravitational pull power
self.radius = wellGraphics.width / 2; // Radius of influence
self.active = true; // Whether the gravity well is active
// Increase the gravity well's power
self.increasePower = function (amount) {
self.power += amount;
// Visual feedback - pulse the well
tween(wellGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(wellGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
};
// Deactivate the gravity well temporarily
self.deactivate = function (duration) {
self.active = false;
wellGraphics.alpha = 0.2;
coreGraphics.alpha = 0.2;
LK.setTimeout(function () {
self.active = true;
wellGraphics.alpha = 0.5;
coreGraphics.alpha = 1;
}, duration);
};
// Pulse animation for the well
self.pulse = function () {
tween(wellGraphics, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(wellGraphics, {
alpha: 0.5
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
// Create star visual
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
alpha: Math.random() * 0.7 + 0.3 // Random brightness
});
// Set random scale for varied star sizes
var starScale = Math.random() * 0.7 + 0.3;
starGraphics.scale.x = starGraphics.scale.y = starScale;
// Set random movement speed (for parallax effect)
self.speed = starScale * 0.5; // Larger stars move faster for parallax effect
// Update method called every tick
self.update = function () {
self.y += self.speed;
// Reset position when star goes off screen
if (self.y > 2732) {
self.y = 0;
self.x = Math.random() * 2048;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Create background with stars
var stars = [];
for (var i = 0; i < 100; i++) {
var star = new Star();
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
stars.push(star);
game.addChild(star);
}
// Game variables
var gravityWell;
var cosmicObjects = [];
var gameActive = true;
var spawnTimer;
var difficultyTimer;
var difficulty = 1;
var lastUpdateTime = Date.now();
// UI elements
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.setText('Score: ' + LK.getScore());
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 60,
fill: 0xAAAAFF
});
highScoreTxt.anchor.set(1, 0);
highScoreTxt.x = -20;
highScoreTxt.y = 100;
LK.gui.topRight.addChild(highScoreTxt);
var powerTxt = new Text2('Gravity Power: 1', {
size: 60,
fill: 0x44AAFF
});
powerTxt.anchor.set(0, 0);
powerTxt.y = 100;
LK.gui.topLeft.addChild(powerTxt);
// Initialize gravity well
function initializeGame() {
// Create the gravity well
gravityWell = new GravityWell();
gravityWell.x = 2048 / 2;
gravityWell.y = 2732 / 2;
game.addChild(gravityWell);
// Start cosmic object spawning
spawnTimer = LK.setInterval(spawnCosmicObject, 1000);
// Increase difficulty over time
difficultyTimer = LK.setInterval(function () {
difficulty += 0.2;
gravityWell.pulse(); // Visual cue that difficulty increased
}, 10000);
// Start background music
LK.playMusic('cosmicAmbience', {
fade: {
start: 0,
end: 0.4,
duration: 2000
}
});
}
// Spawn a cosmic object with random properties
function spawnCosmicObject() {
var rand = Math.random();
var type, speed, points;
if (rand < 0.6) {
// Common cosmic gem
type = 'cosmicGem';
speed = 1 + Math.random() * difficulty;
points = 1;
} else if (rand < 0.85) {
// Rare gem
type = 'rareGem';
speed = 1.5 + Math.random() * difficulty;
points = 3;
} else if (rand < 0.95) {
// Space debris (harmful)
type = 'spaceDebris';
speed = 2 + Math.random() * difficulty;
points = -2;
} else {
// Power up
type = 'powerUp';
speed = 1 + Math.random() * difficulty;
points = 0; // Special handling for power ups
}
// Create the object
var object = new CosmicObject(type, speed, points);
// Position randomly at the top of the screen
object.x = Math.random() * 2048;
object.y = -100;
// Add some horizontal velocity for more interesting movement
object.velocityX = (Math.random() - 0.5) * 2;
// Add to game
cosmicObjects.push(object);
game.addChild(object);
}
// Handle dragging the gravity well
var isDragging = false;
game.down = function (x, y) {
// Check if the click is on/near the gravity well
var dx = x - gravityWell.x;
var dy = y - gravityWell.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < gravityWell.radius * 0.5) {
isDragging = true;
}
};
game.up = function () {
isDragging = false;
};
game.move = function (x, y) {
if (isDragging && gameActive) {
gravityWell.x = x;
gravityWell.y = y;
// Keep gravity well within game bounds
gravityWell.x = Math.max(gravityWell.radius, Math.min(2048 - gravityWell.radius, gravityWell.x));
gravityWell.y = Math.max(gravityWell.radius, Math.min(2732 - gravityWell.radius, gravityWell.y));
}
};
// Handle object and gravity interactions
function updateObjects() {
var currentTime = Date.now();
var deltaTime = (currentTime - lastUpdateTime) / 16.67; // Normalize to 60fps
lastUpdateTime = currentTime;
for (var i = cosmicObjects.length - 1; i >= 0; i--) {
var object = cosmicObjects[i];
// Update object position
object.update();
// Check if object is off-screen
if (object.y > 2732 + 100) {
object.destroy();
cosmicObjects.splice(i, 1);
continue;
}
// Apply gravity pull and check for capture
if (object.applyGravity(gravityWell, deltaTime)) {
// Object is captured
if (object.type === 'powerUp') {
// Power up increases gravity well strength
gravityWell.increasePower(0.2);
powerTxt.setText('Gravity Power: ' + gravityWell.power.toFixed(1));
LK.getSound('powerup').play();
LK.effects.flashObject(gravityWell, 0x22ff44, 500);
} else if (object.type === 'spaceDebris') {
// Space debris damages the gravity well
gravityWell.deactivate(2000);
LK.getSound('danger').play();
LK.effects.flashObject(gravityWell, 0xff2222, 500);
// Decrease score
LK.setScore(Math.max(0, LK.getScore() + object.pointValue));
scoreTxt.setText('Score: ' + LK.getScore());
} else {
// Regular cosmic objects increase score
LK.setScore(LK.getScore() + object.pointValue);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('collect').play();
}
// Remove the captured object
object.destroy();
cosmicObjects.splice(i, 1);
// Check win condition
if (LK.getScore() >= 100) {
endGame(true);
}
}
}
}
// Update stars for parallax effect
function updateStars() {
for (var i = 0; i < stars.length; i++) {
stars[i].update();
}
}
// End the game
function endGame(isWin) {
gameActive = false;
// Update high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('High Score: ' + storage.highScore);
}
// Clear timers
LK.clearInterval(spawnTimer);
LK.clearInterval(difficultyTimer);
if (isWin) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// Main game update function
game.update = function () {
if (!gameActive) {
return;
}
updateStars();
updateObjects();
// Gradually increase spawn rate based on difficulty
if (LK.ticks % Math.max(30, Math.floor(120 / difficulty)) === 0) {
spawnCosmicObject();
}
};
// Initialize the game
initializeGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var CosmicObject = Container.expand(function (type, speed, pointValue) {
var self = Container.call(this);
// Set default values if not provided
self.type = type || 'cosmicGem';
self.speed = speed || 2;
self.pointValue = pointValue || 1;
// Create the cosmic object visual
var objectGraphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
// Apply random rotation for visual interest
objectGraphics.rotation = Math.random() * Math.PI * 2;
// Define movement properties
self.velocityX = 0;
self.velocityY = self.speed;
self.beingPulled = false;
self.captureProgress = 0; // 0 to 1, where 1 means captured
// Update method called every tick
self.update = function () {
if (!self.beingPulled) {
// Normal movement
self.x += self.velocityX;
self.y += self.velocityY;
}
};
// Apply gravitational pull from the well
self.applyGravity = function (well, deltaTime) {
if (!well.active) {
return;
}
// Calculate distance between object and gravity well
var dx = well.x - self.x;
var dy = well.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Only apply gravity if within the well's influence
if (distance < well.radius) {
self.beingPulled = true;
// Calculate pull strength based on distance and well power
var pullStrength = Math.min(0.1, (well.radius - distance) / well.radius * 0.2) * well.power;
// Apply gravitational pull
self.velocityX += dx * pullStrength;
self.velocityY += dy * pullStrength;
// Apply velocity with damping for stability
self.x += self.velocityX * deltaTime;
self.y += self.velocityY * deltaTime;
// Increase capture progress when very close to the well
if (distance < well.radius * 0.2) {
self.captureProgress += 0.03;
// Visual feedback - scale down as being captured
objectGraphics.scale.x = objectGraphics.scale.y = 1 - self.captureProgress * 0.2;
// Object is fully captured
if (self.captureProgress >= 1) {
return true; // Signal that object is captured
}
}
} else {
self.beingPulled = false;
}
return false; // Not captured yet
};
return self;
});
var GravityWell = Container.expand(function () {
var self = Container.call(this);
// Create the gravity well visuals
var wellGraphics = self.attachAsset('gravityWell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Create the core of the gravity well
var coreGraphics = self.attachAsset('wellCore', {
anchorX: 0.5,
anchorY: 0.5
});
self.power = 1; // Base gravitational pull power
self.radius = wellGraphics.width / 2; // Radius of influence
self.active = true; // Whether the gravity well is active
// Increase the gravity well's power
self.increasePower = function (amount) {
self.power += amount;
// Visual feedback - pulse the well
tween(wellGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(wellGraphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
};
// Deactivate the gravity well temporarily
self.deactivate = function (duration) {
self.active = false;
wellGraphics.alpha = 0.2;
coreGraphics.alpha = 0.2;
LK.setTimeout(function () {
self.active = true;
wellGraphics.alpha = 0.5;
coreGraphics.alpha = 1;
}, duration);
};
// Pulse animation for the well
self.pulse = function () {
tween(wellGraphics, {
alpha: 0.7
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(wellGraphics, {
alpha: 0.5
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
// Create star visual
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
alpha: Math.random() * 0.7 + 0.3 // Random brightness
});
// Set random scale for varied star sizes
var starScale = Math.random() * 0.7 + 0.3;
starGraphics.scale.x = starGraphics.scale.y = starScale;
// Set random movement speed (for parallax effect)
self.speed = starScale * 0.5; // Larger stars move faster for parallax effect
// Update method called every tick
self.update = function () {
self.y += self.speed;
// Reset position when star goes off screen
if (self.y > 2732) {
self.y = 0;
self.x = Math.random() * 2048;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Create background with stars
var stars = [];
for (var i = 0; i < 100; i++) {
var star = new Star();
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
stars.push(star);
game.addChild(star);
}
// Game variables
var gravityWell;
var cosmicObjects = [];
var gameActive = true;
var spawnTimer;
var difficultyTimer;
var difficulty = 1;
var lastUpdateTime = Date.now();
// UI elements
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.setText('Score: ' + LK.getScore());
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 60,
fill: 0xAAAAFF
});
highScoreTxt.anchor.set(1, 0);
highScoreTxt.x = -20;
highScoreTxt.y = 100;
LK.gui.topRight.addChild(highScoreTxt);
var powerTxt = new Text2('Gravity Power: 1', {
size: 60,
fill: 0x44AAFF
});
powerTxt.anchor.set(0, 0);
powerTxt.y = 100;
LK.gui.topLeft.addChild(powerTxt);
// Initialize gravity well
function initializeGame() {
// Create the gravity well
gravityWell = new GravityWell();
gravityWell.x = 2048 / 2;
gravityWell.y = 2732 / 2;
game.addChild(gravityWell);
// Start cosmic object spawning
spawnTimer = LK.setInterval(spawnCosmicObject, 1000);
// Increase difficulty over time
difficultyTimer = LK.setInterval(function () {
difficulty += 0.2;
gravityWell.pulse(); // Visual cue that difficulty increased
}, 10000);
// Start background music
LK.playMusic('cosmicAmbience', {
fade: {
start: 0,
end: 0.4,
duration: 2000
}
});
}
// Spawn a cosmic object with random properties
function spawnCosmicObject() {
var rand = Math.random();
var type, speed, points;
if (rand < 0.6) {
// Common cosmic gem
type = 'cosmicGem';
speed = 1 + Math.random() * difficulty;
points = 1;
} else if (rand < 0.85) {
// Rare gem
type = 'rareGem';
speed = 1.5 + Math.random() * difficulty;
points = 3;
} else if (rand < 0.95) {
// Space debris (harmful)
type = 'spaceDebris';
speed = 2 + Math.random() * difficulty;
points = -2;
} else {
// Power up
type = 'powerUp';
speed = 1 + Math.random() * difficulty;
points = 0; // Special handling for power ups
}
// Create the object
var object = new CosmicObject(type, speed, points);
// Position randomly at the top of the screen
object.x = Math.random() * 2048;
object.y = -100;
// Add some horizontal velocity for more interesting movement
object.velocityX = (Math.random() - 0.5) * 2;
// Add to game
cosmicObjects.push(object);
game.addChild(object);
}
// Handle dragging the gravity well
var isDragging = false;
game.down = function (x, y) {
// Check if the click is on/near the gravity well
var dx = x - gravityWell.x;
var dy = y - gravityWell.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < gravityWell.radius * 0.5) {
isDragging = true;
}
};
game.up = function () {
isDragging = false;
};
game.move = function (x, y) {
if (isDragging && gameActive) {
gravityWell.x = x;
gravityWell.y = y;
// Keep gravity well within game bounds
gravityWell.x = Math.max(gravityWell.radius, Math.min(2048 - gravityWell.radius, gravityWell.x));
gravityWell.y = Math.max(gravityWell.radius, Math.min(2732 - gravityWell.radius, gravityWell.y));
}
};
// Handle object and gravity interactions
function updateObjects() {
var currentTime = Date.now();
var deltaTime = (currentTime - lastUpdateTime) / 16.67; // Normalize to 60fps
lastUpdateTime = currentTime;
for (var i = cosmicObjects.length - 1; i >= 0; i--) {
var object = cosmicObjects[i];
// Update object position
object.update();
// Check if object is off-screen
if (object.y > 2732 + 100) {
object.destroy();
cosmicObjects.splice(i, 1);
continue;
}
// Apply gravity pull and check for capture
if (object.applyGravity(gravityWell, deltaTime)) {
// Object is captured
if (object.type === 'powerUp') {
// Power up increases gravity well strength
gravityWell.increasePower(0.2);
powerTxt.setText('Gravity Power: ' + gravityWell.power.toFixed(1));
LK.getSound('powerup').play();
LK.effects.flashObject(gravityWell, 0x22ff44, 500);
} else if (object.type === 'spaceDebris') {
// Space debris damages the gravity well
gravityWell.deactivate(2000);
LK.getSound('danger').play();
LK.effects.flashObject(gravityWell, 0xff2222, 500);
// Decrease score
LK.setScore(Math.max(0, LK.getScore() + object.pointValue));
scoreTxt.setText('Score: ' + LK.getScore());
} else {
// Regular cosmic objects increase score
LK.setScore(LK.getScore() + object.pointValue);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('collect').play();
}
// Remove the captured object
object.destroy();
cosmicObjects.splice(i, 1);
// Check win condition
if (LK.getScore() >= 100) {
endGame(true);
}
}
}
}
// Update stars for parallax effect
function updateStars() {
for (var i = 0; i < stars.length; i++) {
stars[i].update();
}
}
// End the game
function endGame(isWin) {
gameActive = false;
// Update high score
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
highScoreTxt.setText('High Score: ' + storage.highScore);
}
// Clear timers
LK.clearInterval(spawnTimer);
LK.clearInterval(difficultyTimer);
if (isWin) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// Main game update function
game.update = function () {
if (!gameActive) {
return;
}
updateStars();
updateObjects();
// Gradually increase spawn rate based on difficulty
if (LK.ticks % Math.max(30, Math.floor(120 / difficulty)) === 0) {
spawnCosmicObject();
}
};
// Initialize the game
initializeGame();