/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
energyRecord: 0,
shipsUnlocked: 1
});
/****
* Classes
****/
var EnergyOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('energyOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.speed = 5;
// Glow effect
self.glowFactor = 0;
self.glowDirection = 1;
self.update = function () {
// Move upwards (towards player)
self.y += self.speed;
// Apply glow effect
self.glowFactor += 0.05 * self.glowDirection;
if (self.glowFactor >= 1) {
self.glowDirection = -1;
} else if (self.glowFactor <= 0) {
self.glowDirection = 1;
}
orbGraphics.scaleX = 1 + self.glowFactor * 0.2;
orbGraphics.scaleY = 1 + self.glowFactor * 0.2;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.rotationSpeed = Math.random() * 0.04 - 0.02;
self.update = function () {
// Move upwards (towards player)
self.y += self.speed;
// Rotate the obstacle
obstacleGraphics.rotation += self.rotationSpeed;
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 0,
y: 0
};
self.maxSpeed = 20;
self.driftFactor = 0.92;
self.acceleration = 0.25;
self.energy = 0;
self.maxEnergy = 100;
self.isBoostActive = false;
self.boostTimer = 0;
self.boostDuration = 60; // 1 second at 60fps
self.isInvulnerable = false;
self.invulnerabilityTimer = 0;
// Spawn boost trail particles
self.createBoostTrail = function () {
if (self.isBoostActive && LK.ticks % 3 === 0) {
var trail = LK.getAsset('boostTrail', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x - 50 + (Math.random() * 20 - 10),
y: self.y + 40 + (Math.random() * 20 - 10),
alpha: 0.8
});
game.addChild(trail);
boostTrails.push(trail);
tween(trail, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
onFinish: function onFinish() {
game.removeChild(trail);
var index = boostTrails.indexOf(trail);
if (index > -1) {
boostTrails.splice(index, 1);
}
}
});
}
};
self.activateBoost = function () {
if (self.energy >= 30 && !self.isBoostActive) {
self.isBoostActive = true;
self.boostTimer = self.boostDuration;
self.energy -= 30;
// Flash ship with green tint for boost
LK.effects.flashObject(shipGraphics, 0x2ecc71, 300);
// Play boost sound
LK.getSound('boost').play();
}
};
self.hit = function () {
if (!self.isInvulnerable) {
// Apply damage and make invulnerable briefly
self.velocity.x *= -0.5;
self.velocity.y *= 0.5;
// Play crash sound
LK.getSound('crash').play();
// Flash ship with red tint for damage
LK.effects.flashObject(shipGraphics, 0xff0000, 500);
self.isInvulnerable = true;
self.invulnerabilityTimer = 90; // 1.5 seconds at 60fps
}
};
self.update = function () {
// Update boost status
if (self.isBoostActive) {
self.boostTimer--;
if (self.boostTimer <= 0) {
self.isBoostActive = false;
}
}
// Update invulnerability status
if (self.isInvulnerable) {
self.invulnerabilityTimer--;
shipGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.5) * 0.5;
if (self.invulnerabilityTimer <= 0) {
self.isInvulnerable = false;
shipGraphics.alpha = 1;
}
}
// Apply movement physics
if (self.isBoostActive) {
self.velocity.y -= self.acceleration * 2;
}
// Apply drift physics
self.velocity.x *= self.driftFactor;
// Limit speed
var currentSpeed = Math.sqrt(self.velocity.x * self.velocity.x + self.velocity.y * self.velocity.y);
var maxSpeedValue = self.isBoostActive ? self.maxSpeed * 1.5 : self.maxSpeed;
if (currentSpeed > maxSpeedValue) {
var ratio = maxSpeedValue / currentSpeed;
self.velocity.x *= ratio;
self.velocity.y *= ratio;
}
// Update position
self.x += self.velocity.x;
self.y += self.velocity.y;
// Keep ship in bounds (horizontally)
if (self.x < 150) {
self.x = 150;
self.velocity.x *= -0.5;
} else if (self.x > 2048 - 150) {
self.x = 2048 - 150;
self.velocity.x *= -0.5;
}
// Apply rotation based on horizontal movement
var targetRotation = self.velocity.x / self.maxSpeed * 0.6;
shipGraphics.rotation = targetRotation;
// Create boost trail particles
self.createBoostTrail();
};
return self;
});
var TrackSegment = Container.expand(function () {
var self = Container.call(this);
var segmentGraphics = self.attachAsset('trackSegment', {
anchorX: 0.5,
anchorY: 0
});
self.speed = 6;
// Add stars for the track
for (var i = 0; i < 15; i++) {
var star = LK.getAsset('starField', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * segmentGraphics.width - segmentGraphics.width / 2,
y: Math.random() * segmentGraphics.height,
alpha: 0.2 + Math.random() * 0.8,
scaleX: 0.2 + Math.random() * 0.8,
scaleY: 0.2 + Math.random() * 0.8
});
self.addChild(star);
}
self.update = function () {
// Move upwards
self.y += self.speed;
};
return self;
});
var Wormhole = Container.expand(function () {
var self = Container.call(this);
var wormholeGraphics = self.attachAsset('wormhole', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.portalTarget = null;
self.isActive = true;
self.cooldown = 0;
// Spin effect
self.update = function () {
// Move upwards (towards player)
self.y += self.speed;
// Rotate the wormhole
wormholeGraphics.rotation += 0.02;
// Pulse effect
var pulse = (Math.sin(LK.ticks * 0.05) + 1) * 0.1;
wormholeGraphics.scaleX = 1 + pulse;
wormholeGraphics.scaleY = 1 + pulse;
// Update cooldown
if (self.cooldown > 0) {
self.cooldown--;
wormholeGraphics.alpha = 0.5;
if (self.cooldown === 0) {
self.isActive = true;
wormholeGraphics.alpha = 1;
}
}
};
self.transport = function (ship) {
if (self.isActive && self.portalTarget) {
// Play wormhole sound
LK.getSound('wormhole').play();
// Transport the ship
ship.x = self.portalTarget.x;
ship.y = self.portalTarget.y - 150;
// Apply small boost in y direction
ship.velocity.y -= 5;
// Deactivate this wormhole temporarily
self.isActive = false;
self.cooldown = 120; // 2 seconds at 60fps
// Also deactivate the target wormhole
if (self.portalTarget.isActive) {
self.portalTarget.isActive = false;
self.portalTarget.cooldown = 120;
}
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var ship;
var trackSegments = [];
var energyOrbs = [];
var obstacles = [];
var wormholes = [];
var boostTrails = [];
var lastTrackY = 0;
var score = 0;
var distance = 0;
var gameStarted = false;
var dragNode = null;
var spawnRateMultiplier = 1;
// UI Variables
var scoreText;
var energyBar;
var energyBarBg;
var distanceText;
var highScoreText;
var energyText;
var startText;
// Initialize the game
function initGame() {
// Set up background
game.setBackgroundColor(0x0a0a20);
// Initialize UI
setupUI();
// Create player ship
ship = new Ship();
ship.x = 2048 / 2;
ship.y = 2732 - 400;
game.addChild(ship);
// Start with several track segments
for (var i = 0; i < 10; i++) {
createTrackSegment(2732 - i * 300);
}
// Start game music
LK.playMusic('racingMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Initialize game state
gameStarted = false;
score = 0;
distance = 0;
// Set initial positions
ship.velocity = {
x: 0,
y: 0
};
ship.energy = 0;
// Update UI to show start text
startText.visible = true;
updateUI();
}
function setupUI() {
// Create score text
scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -200;
scoreText.y = 50;
// Create distance text
distanceText = new Text2('Distance: 0', {
size: 50,
fill: 0xFFFFFF
});
distanceText.anchor.set(0, 0);
LK.gui.topRight.addChild(distanceText);
distanceText.x = -200;
distanceText.y = 110;
// Create energy bar background
energyBarBg = LK.getAsset('bullet', {
width: 400,
height: 30,
color: 0x333333,
anchorX: 0,
anchorY: 0
});
LK.gui.top.addChild(energyBarBg);
energyBarBg.x = -200;
energyBarBg.y = 50;
// Create energy bar
energyBar = LK.getAsset('bullet', {
width: 0,
height: 30,
color: 0x2ecc71,
anchorX: 0,
anchorY: 0
});
LK.gui.top.addChild(energyBar);
energyBar.x = -200;
energyBar.y = 50;
// Create energy text
energyText = new Text2('Energy', {
size: 30,
fill: 0xFFFFFF
});
energyText.anchor.set(0.5, 0.5);
LK.gui.top.addChild(energyText);
energyText.x = 0;
energyText.y = 65;
// Create high score text
highScoreText = new Text2('High Score: ' + storage.highScore, {
size: 40,
fill: 0xF1C40F
});
highScoreText.anchor.set(0, 0);
LK.gui.top.addChild(highScoreText);
highScoreText.x = 50;
highScoreText.y = 50;
// Create start text
startText = new Text2('Tap and drag to control ship\nDouble tap to use boost', {
size: 60,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
}
function updateUI() {
// Update score text
scoreText.setText('Score: ' + score);
// Update distance text
distanceText.setText('Distance: ' + Math.floor(distance / 100));
// Update energy bar
energyBar.width = ship.energy / ship.maxEnergy * 400;
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreText.setText('High Score: ' + storage.highScore);
}
}
// Create a new track segment
function createTrackSegment(yPos) {
var segment = new TrackSegment();
segment.x = 2048 / 2;
segment.y = yPos;
game.addChild(segment);
trackSegments.push(segment);
lastTrackY = yPos;
}
// Spawn a random element (energy orb, obstacle, or wormhole)
function spawnRandomElement() {
var randomValue = Math.random();
if (randomValue < 0.6) {
// Spawn energy orb
spawnEnergyOrb();
} else if (randomValue < 0.9) {
// Spawn obstacle
spawnObstacle();
} else {
// Spawn wormhole pair
spawnWormholePair();
}
}
// Spawn energy orb
function spawnEnergyOrb() {
var orb = new EnergyOrb();
orb.x = 300 + Math.random() * (2048 - 600);
orb.y = -100;
game.addChild(orb);
energyOrbs.push(orb);
}
// Spawn obstacle
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 300 + Math.random() * (2048 - 600);
obstacle.y = -100;
game.addChild(obstacle);
obstacles.push(obstacle);
}
// Spawn a pair of connected wormholes
function spawnWormholePair() {
var wormhole1 = new Wormhole();
wormhole1.x = 400 + Math.random() * 500;
wormhole1.y = -100;
var wormhole2 = new Wormhole();
wormhole2.x = 2048 - 400 - Math.random() * 500;
wormhole2.y = -800 - Math.random() * 500;
// Link the wormholes to each other
wormhole1.portalTarget = wormhole2;
wormhole2.portalTarget = wormhole1;
game.addChild(wormhole1);
game.addChild(wormhole2);
wormholes.push(wormhole1);
wormholes.push(wormhole2);
}
// Handle movement event
function handleMove(x, y, obj) {
if (dragNode && gameStarted) {
// Calculate the drag influence
var targetX = x;
var deltaX = targetX - dragNode.x;
// Apply movement force to ship
dragNode.velocity.x += deltaX * 0.1;
}
}
// Game initialization
initGame();
// Handle touch down on game
game.down = function (x, y, obj) {
var currentTime = Date.now();
if (!gameStarted) {
// Start game on first tap
gameStarted = true;
startText.visible = false;
return;
}
// Set drag node to ship
dragNode = ship;
// Handle double tap for boost
if (ship.lastTapTime && currentTime - ship.lastTapTime < 300) {
ship.activateBoost();
}
ship.lastTapTime = currentTime;
// Call move handler right away for instant effect
handleMove(x, y, obj);
};
// Handle touch up on game
game.up = function (x, y, obj) {
dragNode = null;
};
// Handle move events
game.move = handleMove;
// Main game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Update distance and score
distance += ship.isBoostActive ? 12 : 6;
score = Math.floor(distance / 100) + ship.energy * 2;
// Update difficulty
spawnRateMultiplier = 1 + distance / 50000;
// Update track segments
for (var i = trackSegments.length - 1; i >= 0; i--) {
var segment = trackSegments[i];
// Remove off-screen segments
if (segment.y > 2732 + 300) {
game.removeChild(segment);
trackSegments.splice(i, 1);
}
}
// Spawn new track segments as needed
if (lastTrackY > -300) {
createTrackSegment(-300);
}
// Randomly spawn game elements
if (LK.ticks % Math.floor(50 / spawnRateMultiplier) === 0) {
spawnRandomElement();
}
// Update energy orbs
for (var i = energyOrbs.length - 1; i >= 0; i--) {
var orb = energyOrbs[i];
// Check for collisions with ship
if (orb.intersects(ship)) {
// Collect energy
ship.energy = Math.min(ship.maxEnergy, ship.energy + orb.value);
// Play collect sound
LK.getSound('collect').play();
// Remove orb
game.removeChild(orb);
energyOrbs.splice(i, 1);
// Add to score
score += 50;
// Track energy collection record
if (ship.energy > storage.energyRecord) {
storage.energyRecord = ship.energy;
}
continue;
}
// Remove off-screen orbs
if (orb.y > 2732 + 100) {
game.removeChild(orb);
energyOrbs.splice(i, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
// Check for collisions with ship
if (obstacle.intersects(ship)) {
ship.hit();
// Reduce energy
ship.energy = Math.max(0, ship.energy - 20);
// Remove obstacle
game.removeChild(obstacle);
obstacles.splice(i, 1);
continue;
}
// Remove off-screen obstacles
if (obstacle.y > 2732 + 100) {
game.removeChild(obstacle);
obstacles.splice(i, 1);
}
}
// Update wormholes
for (var i = wormholes.length - 1; i >= 0; i--) {
var wormhole = wormholes[i];
// Check for collisions with ship
if (wormhole.intersects(ship)) {
var transported = wormhole.transport(ship);
if (transported) {
// Add to score for successful wormhole transport
score += 100;
}
}
// Remove off-screen wormholes
if (wormhole.y > 2732 + 100) {
// If this wormhole has a partner, remove the link
if (wormhole.portalTarget) {
wormhole.portalTarget.portalTarget = null;
}
game.removeChild(wormhole);
wormholes.splice(i, 1);
}
}
// Game over condition (more obstacles could be added later)
if (ship.y < 0) {
// Record high score
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over
LK.showGameOver();
}
// Update UI
updateUI();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
energyRecord: 0,
shipsUnlocked: 1
});
/****
* Classes
****/
var EnergyOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('energyOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.speed = 5;
// Glow effect
self.glowFactor = 0;
self.glowDirection = 1;
self.update = function () {
// Move upwards (towards player)
self.y += self.speed;
// Apply glow effect
self.glowFactor += 0.05 * self.glowDirection;
if (self.glowFactor >= 1) {
self.glowDirection = -1;
} else if (self.glowFactor <= 0) {
self.glowDirection = 1;
}
orbGraphics.scaleX = 1 + self.glowFactor * 0.2;
orbGraphics.scaleY = 1 + self.glowFactor * 0.2;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.rotationSpeed = Math.random() * 0.04 - 0.02;
self.update = function () {
// Move upwards (towards player)
self.y += self.speed;
// Rotate the obstacle
obstacleGraphics.rotation += self.rotationSpeed;
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = {
x: 0,
y: 0
};
self.maxSpeed = 20;
self.driftFactor = 0.92;
self.acceleration = 0.25;
self.energy = 0;
self.maxEnergy = 100;
self.isBoostActive = false;
self.boostTimer = 0;
self.boostDuration = 60; // 1 second at 60fps
self.isInvulnerable = false;
self.invulnerabilityTimer = 0;
// Spawn boost trail particles
self.createBoostTrail = function () {
if (self.isBoostActive && LK.ticks % 3 === 0) {
var trail = LK.getAsset('boostTrail', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x - 50 + (Math.random() * 20 - 10),
y: self.y + 40 + (Math.random() * 20 - 10),
alpha: 0.8
});
game.addChild(trail);
boostTrails.push(trail);
tween(trail, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
onFinish: function onFinish() {
game.removeChild(trail);
var index = boostTrails.indexOf(trail);
if (index > -1) {
boostTrails.splice(index, 1);
}
}
});
}
};
self.activateBoost = function () {
if (self.energy >= 30 && !self.isBoostActive) {
self.isBoostActive = true;
self.boostTimer = self.boostDuration;
self.energy -= 30;
// Flash ship with green tint for boost
LK.effects.flashObject(shipGraphics, 0x2ecc71, 300);
// Play boost sound
LK.getSound('boost').play();
}
};
self.hit = function () {
if (!self.isInvulnerable) {
// Apply damage and make invulnerable briefly
self.velocity.x *= -0.5;
self.velocity.y *= 0.5;
// Play crash sound
LK.getSound('crash').play();
// Flash ship with red tint for damage
LK.effects.flashObject(shipGraphics, 0xff0000, 500);
self.isInvulnerable = true;
self.invulnerabilityTimer = 90; // 1.5 seconds at 60fps
}
};
self.update = function () {
// Update boost status
if (self.isBoostActive) {
self.boostTimer--;
if (self.boostTimer <= 0) {
self.isBoostActive = false;
}
}
// Update invulnerability status
if (self.isInvulnerable) {
self.invulnerabilityTimer--;
shipGraphics.alpha = 0.5 + Math.sin(LK.ticks * 0.5) * 0.5;
if (self.invulnerabilityTimer <= 0) {
self.isInvulnerable = false;
shipGraphics.alpha = 1;
}
}
// Apply movement physics
if (self.isBoostActive) {
self.velocity.y -= self.acceleration * 2;
}
// Apply drift physics
self.velocity.x *= self.driftFactor;
// Limit speed
var currentSpeed = Math.sqrt(self.velocity.x * self.velocity.x + self.velocity.y * self.velocity.y);
var maxSpeedValue = self.isBoostActive ? self.maxSpeed * 1.5 : self.maxSpeed;
if (currentSpeed > maxSpeedValue) {
var ratio = maxSpeedValue / currentSpeed;
self.velocity.x *= ratio;
self.velocity.y *= ratio;
}
// Update position
self.x += self.velocity.x;
self.y += self.velocity.y;
// Keep ship in bounds (horizontally)
if (self.x < 150) {
self.x = 150;
self.velocity.x *= -0.5;
} else if (self.x > 2048 - 150) {
self.x = 2048 - 150;
self.velocity.x *= -0.5;
}
// Apply rotation based on horizontal movement
var targetRotation = self.velocity.x / self.maxSpeed * 0.6;
shipGraphics.rotation = targetRotation;
// Create boost trail particles
self.createBoostTrail();
};
return self;
});
var TrackSegment = Container.expand(function () {
var self = Container.call(this);
var segmentGraphics = self.attachAsset('trackSegment', {
anchorX: 0.5,
anchorY: 0
});
self.speed = 6;
// Add stars for the track
for (var i = 0; i < 15; i++) {
var star = LK.getAsset('starField', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * segmentGraphics.width - segmentGraphics.width / 2,
y: Math.random() * segmentGraphics.height,
alpha: 0.2 + Math.random() * 0.8,
scaleX: 0.2 + Math.random() * 0.8,
scaleY: 0.2 + Math.random() * 0.8
});
self.addChild(star);
}
self.update = function () {
// Move upwards
self.y += self.speed;
};
return self;
});
var Wormhole = Container.expand(function () {
var self = Container.call(this);
var wormholeGraphics = self.attachAsset('wormhole', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.portalTarget = null;
self.isActive = true;
self.cooldown = 0;
// Spin effect
self.update = function () {
// Move upwards (towards player)
self.y += self.speed;
// Rotate the wormhole
wormholeGraphics.rotation += 0.02;
// Pulse effect
var pulse = (Math.sin(LK.ticks * 0.05) + 1) * 0.1;
wormholeGraphics.scaleX = 1 + pulse;
wormholeGraphics.scaleY = 1 + pulse;
// Update cooldown
if (self.cooldown > 0) {
self.cooldown--;
wormholeGraphics.alpha = 0.5;
if (self.cooldown === 0) {
self.isActive = true;
wormholeGraphics.alpha = 1;
}
}
};
self.transport = function (ship) {
if (self.isActive && self.portalTarget) {
// Play wormhole sound
LK.getSound('wormhole').play();
// Transport the ship
ship.x = self.portalTarget.x;
ship.y = self.portalTarget.y - 150;
// Apply small boost in y direction
ship.velocity.y -= 5;
// Deactivate this wormhole temporarily
self.isActive = false;
self.cooldown = 120; // 2 seconds at 60fps
// Also deactivate the target wormhole
if (self.portalTarget.isActive) {
self.portalTarget.isActive = false;
self.portalTarget.cooldown = 120;
}
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var ship;
var trackSegments = [];
var energyOrbs = [];
var obstacles = [];
var wormholes = [];
var boostTrails = [];
var lastTrackY = 0;
var score = 0;
var distance = 0;
var gameStarted = false;
var dragNode = null;
var spawnRateMultiplier = 1;
// UI Variables
var scoreText;
var energyBar;
var energyBarBg;
var distanceText;
var highScoreText;
var energyText;
var startText;
// Initialize the game
function initGame() {
// Set up background
game.setBackgroundColor(0x0a0a20);
// Initialize UI
setupUI();
// Create player ship
ship = new Ship();
ship.x = 2048 / 2;
ship.y = 2732 - 400;
game.addChild(ship);
// Start with several track segments
for (var i = 0; i < 10; i++) {
createTrackSegment(2732 - i * 300);
}
// Start game music
LK.playMusic('racingMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Initialize game state
gameStarted = false;
score = 0;
distance = 0;
// Set initial positions
ship.velocity = {
x: 0,
y: 0
};
ship.energy = 0;
// Update UI to show start text
startText.visible = true;
updateUI();
}
function setupUI() {
// Create score text
scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -200;
scoreText.y = 50;
// Create distance text
distanceText = new Text2('Distance: 0', {
size: 50,
fill: 0xFFFFFF
});
distanceText.anchor.set(0, 0);
LK.gui.topRight.addChild(distanceText);
distanceText.x = -200;
distanceText.y = 110;
// Create energy bar background
energyBarBg = LK.getAsset('bullet', {
width: 400,
height: 30,
color: 0x333333,
anchorX: 0,
anchorY: 0
});
LK.gui.top.addChild(energyBarBg);
energyBarBg.x = -200;
energyBarBg.y = 50;
// Create energy bar
energyBar = LK.getAsset('bullet', {
width: 0,
height: 30,
color: 0x2ecc71,
anchorX: 0,
anchorY: 0
});
LK.gui.top.addChild(energyBar);
energyBar.x = -200;
energyBar.y = 50;
// Create energy text
energyText = new Text2('Energy', {
size: 30,
fill: 0xFFFFFF
});
energyText.anchor.set(0.5, 0.5);
LK.gui.top.addChild(energyText);
energyText.x = 0;
energyText.y = 65;
// Create high score text
highScoreText = new Text2('High Score: ' + storage.highScore, {
size: 40,
fill: 0xF1C40F
});
highScoreText.anchor.set(0, 0);
LK.gui.top.addChild(highScoreText);
highScoreText.x = 50;
highScoreText.y = 50;
// Create start text
startText = new Text2('Tap and drag to control ship\nDouble tap to use boost', {
size: 60,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startText);
}
function updateUI() {
// Update score text
scoreText.setText('Score: ' + score);
// Update distance text
distanceText.setText('Distance: ' + Math.floor(distance / 100));
// Update energy bar
energyBar.width = ship.energy / ship.maxEnergy * 400;
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreText.setText('High Score: ' + storage.highScore);
}
}
// Create a new track segment
function createTrackSegment(yPos) {
var segment = new TrackSegment();
segment.x = 2048 / 2;
segment.y = yPos;
game.addChild(segment);
trackSegments.push(segment);
lastTrackY = yPos;
}
// Spawn a random element (energy orb, obstacle, or wormhole)
function spawnRandomElement() {
var randomValue = Math.random();
if (randomValue < 0.6) {
// Spawn energy orb
spawnEnergyOrb();
} else if (randomValue < 0.9) {
// Spawn obstacle
spawnObstacle();
} else {
// Spawn wormhole pair
spawnWormholePair();
}
}
// Spawn energy orb
function spawnEnergyOrb() {
var orb = new EnergyOrb();
orb.x = 300 + Math.random() * (2048 - 600);
orb.y = -100;
game.addChild(orb);
energyOrbs.push(orb);
}
// Spawn obstacle
function spawnObstacle() {
var obstacle = new Obstacle();
obstacle.x = 300 + Math.random() * (2048 - 600);
obstacle.y = -100;
game.addChild(obstacle);
obstacles.push(obstacle);
}
// Spawn a pair of connected wormholes
function spawnWormholePair() {
var wormhole1 = new Wormhole();
wormhole1.x = 400 + Math.random() * 500;
wormhole1.y = -100;
var wormhole2 = new Wormhole();
wormhole2.x = 2048 - 400 - Math.random() * 500;
wormhole2.y = -800 - Math.random() * 500;
// Link the wormholes to each other
wormhole1.portalTarget = wormhole2;
wormhole2.portalTarget = wormhole1;
game.addChild(wormhole1);
game.addChild(wormhole2);
wormholes.push(wormhole1);
wormholes.push(wormhole2);
}
// Handle movement event
function handleMove(x, y, obj) {
if (dragNode && gameStarted) {
// Calculate the drag influence
var targetX = x;
var deltaX = targetX - dragNode.x;
// Apply movement force to ship
dragNode.velocity.x += deltaX * 0.1;
}
}
// Game initialization
initGame();
// Handle touch down on game
game.down = function (x, y, obj) {
var currentTime = Date.now();
if (!gameStarted) {
// Start game on first tap
gameStarted = true;
startText.visible = false;
return;
}
// Set drag node to ship
dragNode = ship;
// Handle double tap for boost
if (ship.lastTapTime && currentTime - ship.lastTapTime < 300) {
ship.activateBoost();
}
ship.lastTapTime = currentTime;
// Call move handler right away for instant effect
handleMove(x, y, obj);
};
// Handle touch up on game
game.up = function (x, y, obj) {
dragNode = null;
};
// Handle move events
game.move = handleMove;
// Main game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Update distance and score
distance += ship.isBoostActive ? 12 : 6;
score = Math.floor(distance / 100) + ship.energy * 2;
// Update difficulty
spawnRateMultiplier = 1 + distance / 50000;
// Update track segments
for (var i = trackSegments.length - 1; i >= 0; i--) {
var segment = trackSegments[i];
// Remove off-screen segments
if (segment.y > 2732 + 300) {
game.removeChild(segment);
trackSegments.splice(i, 1);
}
}
// Spawn new track segments as needed
if (lastTrackY > -300) {
createTrackSegment(-300);
}
// Randomly spawn game elements
if (LK.ticks % Math.floor(50 / spawnRateMultiplier) === 0) {
spawnRandomElement();
}
// Update energy orbs
for (var i = energyOrbs.length - 1; i >= 0; i--) {
var orb = energyOrbs[i];
// Check for collisions with ship
if (orb.intersects(ship)) {
// Collect energy
ship.energy = Math.min(ship.maxEnergy, ship.energy + orb.value);
// Play collect sound
LK.getSound('collect').play();
// Remove orb
game.removeChild(orb);
energyOrbs.splice(i, 1);
// Add to score
score += 50;
// Track energy collection record
if (ship.energy > storage.energyRecord) {
storage.energyRecord = ship.energy;
}
continue;
}
// Remove off-screen orbs
if (orb.y > 2732 + 100) {
game.removeChild(orb);
energyOrbs.splice(i, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
// Check for collisions with ship
if (obstacle.intersects(ship)) {
ship.hit();
// Reduce energy
ship.energy = Math.max(0, ship.energy - 20);
// Remove obstacle
game.removeChild(obstacle);
obstacles.splice(i, 1);
continue;
}
// Remove off-screen obstacles
if (obstacle.y > 2732 + 100) {
game.removeChild(obstacle);
obstacles.splice(i, 1);
}
}
// Update wormholes
for (var i = wormholes.length - 1; i >= 0; i--) {
var wormhole = wormholes[i];
// Check for collisions with ship
if (wormhole.intersects(ship)) {
var transported = wormhole.transport(ship);
if (transported) {
// Add to score for successful wormhole transport
score += 100;
}
}
// Remove off-screen wormholes
if (wormhole.y > 2732 + 100) {
// If this wormhole has a partner, remove the link
if (wormhole.portalTarget) {
wormhole.portalTarget.portalTarget = null;
}
game.removeChild(wormhole);
wormholes.splice(i, 1);
}
}
// Game over condition (more obstacles could be added later)
if (ship.y < 0) {
// Record high score
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over
LK.showGameOver();
}
// Update UI
updateUI();
};