/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Obstacle = Container.expand(function (type, x, y) { var self = Container.call(this); self.obstacleType = type || 'spike'; if (self.obstacleType === 'spike') { var obstacleGraphics = self.attachAsset('spike', { anchorX: 0.5, anchorY: 1.0 }); } else if (self.obstacleType === 'platform') { var obstacleGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); } self.x = x || 0; self.y = y || 0; self.speed = -5; self.update = function () { self.x += self.speed; }; return self; }); var Orb = Container.expand(function (x, y) { var self = Container.call(this); var orbGraphics = self.attachAsset('orb', { anchorX: 0.5, anchorY: 0.5 }); self.x = x || 0; self.y = y || 0; self.speed = -5; self.collected = false; self.update = function () { self.x += self.speed; // Gentle floating animation orbGraphics.y = Math.sin(LK.ticks * 0.1) * 10; // Gentle rotation orbGraphics.rotation += 0.05; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.playerGraphics = playerGraphics; // Reference for icon switching // Invincibility overlay (above player) var invOverlay = self.attachAsset('Invincibility-overlay', { anchorX: 0.5, anchorY: 1.0, x: 0, y: -60, // above player, adjust as needed visible: false, alpha: 1 }); // Invincibility state and timer self.isInvincible = false; self.invincibleTicks = 0; self.setInvincible = function (durationTicks) { self.isInvincible = true; self.invincibleTicks = durationTicks; // Show overlay to indicate invincibility if (powerOverlay) { powerOverlay.visible = true; powerOverlay.alpha = 0.7; } // Show invincibility overlay if (invOverlay) { invOverlay.visible = true; } }; self.clearInvincible = function () { self.isInvincible = false; self.invincibleTicks = 0; if (powerOverlay) { powerOverlay.visible = false; powerOverlay.alpha = 0.5; } // Hide invincibility overlay if (invOverlay) { invOverlay.visible = false; } }; self.setIcon = function (iconId) { // Remove old graphics if (self.playerGraphics && self.playerGraphics.parent) { self.playerGraphics.parent.removeChild(self.playerGraphics); } // Add new graphics var newGfx = self.attachAsset(iconId, { anchorX: 0.5, anchorY: 0.5 }); self.playerGraphics = newGfx; // Ensure player icon is always fully opaque if (self.playerGraphics) { self.playerGraphics.alpha = 1; } }; var powerOverlay = self.attachAsset('Orb_powerup_overlay_on_player', { anchorX: 0.5, anchorY: 0.5, visible: false, alpha: 0.5 }); self.velocityY = 0; self.gravity = 0.8; self.jumpPower = -18; self.powerJumpPower = -28; self.hasPowerJump = false; self.isGrounded = false; self.groundY = 2400; self.jump = function () { if (self.isGrounded) { if (self.hasPowerJump) { self.velocityY = self.powerJumpPower; self.hasPowerJump = false; // Fade out power overlay with tween tween(powerOverlay, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { powerOverlay.visible = false; powerOverlay.alpha = 0.5; // Reset alpha for next use } }); // Flash player blue to indicate power jump used LK.effects.flashObject(self, 0x00ffff, 300); // Ensure player icon is always fully opaque if (self.playerGraphics) { self.playerGraphics.alpha = 1; } } else { self.velocityY = self.jumpPower; } self.isGrounded = false; // Start spinning on jump self.spinSpeed = 0.25; // Always spin right, or randomize for variety LK.getSound('jump').play(); } }; self.showPowerOverlay = function () { powerOverlay.visible = true; powerOverlay.alpha = 0.5; // Ensure player icon is always fully opaque if (self.playerGraphics) { self.playerGraphics.alpha = 1; } }; self.hidePowerOverlay = function () { powerOverlay.visible = false; powerOverlay.alpha = 0.5; // Reset alpha for next use // Ensure player icon is always fully opaque if (self.playerGraphics) { self.playerGraphics.alpha = 1; } }; self.update = function () { // Invincibility timer tick down if (self.isInvincible) { if (self.invincibleTicks > 0) { self.invincibleTicks--; if (self.invincibleTicks === 0) { self.clearInvincible(); } } // Ensure invincibility overlay is visible if (invOverlay) invOverlay.visible = true; } else { // Ensure invincibility overlay is hidden if (invOverlay) invOverlay.visible = false; } // Only show rainbow overlay (powerOverlay) if orb powerup is active if (powerOverlay) { if (self.hasPowerJump) { powerOverlay.visible = true; powerOverlay.alpha = 0.5; } else { powerOverlay.visible = false; powerOverlay.alpha = 0.5; } } // --- SPIN LOGIC START --- if (typeof self.lastWasGrounded === "undefined") self.lastWasGrounded = self.isGrounded; if (typeof self.spinSpeed === "undefined") self.spinSpeed = 0; if (typeof self.currentRotation === "undefined") self.currentRotation = 0; // If airborne, spin if (!self.isGrounded) { // Spin direction: positive for right, negative for left (could be random or based on last jump, here always right) if (self.spinSpeed === 0) { // Start spinning with a default speed if just left ground self.spinSpeed = 0.25; } self.currentRotation += self.spinSpeed; if (self.playerGraphics) self.playerGraphics.rotation = self.currentRotation; } else { // On ground, stop spinning but keep rotation if (!self.lastWasGrounded) { // Just landed, keep rotation and stop spin self.spinSpeed = 0; if (self.playerGraphics) self.playerGraphics.rotation = self.currentRotation; } } // Track last grounded state for transition self.lastWasGrounded = self.isGrounded; // --- SPIN LOGIC END --- // Apply gravity self.velocityY += self.gravity; self.y += self.velocityY; // Ground collision if (self.y >= self.groundY) { self.y = self.groundY; self.velocityY = 0; self.isGrounded = true; } // Screen bounds if (self.y < 0) { self.y = 0; self.velocityY = 0; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ var player; var obstacles = []; var orbs = []; var gameSpeed = 5; var spawnTimer = 0; var orbSpawnTimer = 0; var distance = 0; var gameStarted = false; var lastObstacleX = 0; // Background var bg = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 })); // Create player player = game.addChild(new Player()); player.x = 300; player.y = 2400; player.groundY = 2400; // Score display var scoreText = new Text2('Distance: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreText); // Icon kit button (top right, 100x100 safe zone) var iconKitBtn = LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, x: -60, y: 60, scaleX: 0.7, scaleY: 0.7 }); iconKitBtn.interactive = true; iconKitBtn.buttonMode = true; LK.gui.topRight.addChild(iconKitBtn); // Icon selection overlay (hidden by default) var iconOverlayBg = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); iconOverlayBg.alpha = 0.7; iconOverlayBg.visible = false; var iconChoices = []; var iconIds = ['player', 'Icon2', 'Icon3', 'Icon4']; var iconSelectedIndex = 0; // 0 = default for (var i = 0; i < 4; i++) { var icon = LK.getAsset(iconIds[i], { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + (i - 1.5) * 220, y: 2732 / 2, scaleX: 1.5, scaleY: 1.5 }); icon.visible = false; icon.interactive = true; icon.buttonMode = true; icon.iconIndex = i; iconChoices.push(icon); } function showIconOverlay() { iconOverlayBg.visible = true; for (var i = 0; i < iconChoices.length; i++) { iconChoices[i].visible = true; } // Make player invincible while overlay is open (very long duration, will be cleared on hide) if (player && player.setInvincible) { player.setInvincible(999999); // Effectively infinite until overlay is closed } // Game is automatically paused by LK when overlays are shown } function hideIconOverlay() { iconOverlayBg.visible = false; for (var i = 0; i < iconChoices.length; i++) { iconChoices[i].visible = false; } // Grant 5 seconds (300 ticks) invincibility after overlay closes if (player && player.setInvincible) { player.setInvincible(300); } // Game is automatically resumed by LK when overlays are hidden } // Add overlay and icons to game (above everything) game.addChild(iconOverlayBg); for (var i = 0; i < iconChoices.length; i++) { game.addChild(iconChoices[i]); } // Instructions var instructionText = new Text2('TAP TO JUMP', { size: 80, fill: 0xFFFF00 }); instructionText.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionText); // Icon kit button event iconKitBtn.down = function (x, y, obj) { if (!iconOverlayBg.visible) { showIconOverlay(); } }; // Icon selection events for (var i = 0; i < iconChoices.length; i++) { iconChoices[i].down = function (x, y, obj) { var idx = this.iconIndex; iconSelectedIndex = idx; // Change player icon if (player && player.setIcon) { player.setIcon(iconIds[idx]); } hideIconOverlay(); }; } // Hide overlay if background is tapped iconOverlayBg.down = function (x, y, obj) { hideIconOverlay(); }; function startGame() { if (!gameStarted) { gameStarted = true; instructionText.visible = false; LK.playMusic('bgMusic'); } } function resetGame() { // Reset player if (player && player.setIcon && typeof iconSelectedIndex !== "undefined" && typeof iconIds !== "undefined") { player.setIcon(iconIds[iconSelectedIndex]); } player.x = 300; player.y = 2400; player.velocityY = 0; player.isGrounded = true; // Reset spin state player.spinSpeed = 0; player.currentRotation = 0; if (player.playerGraphics) player.playerGraphics.rotation = 0; // Clear obstacles for (var i = obstacles.length - 1; i >= 0; i--) { obstacles[i].destroy(); } obstacles = []; // Clear orbs for (var i = orbs.length - 1; i >= 0; i--) { orbs[i].destroy(); } orbs = []; // Reset player power jump player.hasPowerJump = false; // Hide power overlay player.hidePowerOverlay(); // Reset game state distance = 0; spawnTimer = 0; lastObstacleX = 0; gameStarted = false; instructionText.visible = true; // Flash effect LK.effects.flashScreen(0xff0000, 500); LK.getSound('death').play(); } function spawnOrb() { var orbX = 2048 + 100; var orbY = 2000 + Math.random() * 400; // Random height between ground and air var orb = new Orb(orbX, orbY); orbs.push(orb); game.addChild(orb); } function spawnObstacle() { var minGap = 300; var maxGap = 500; var gap = minGap + Math.random() * (maxGap - minGap); if (lastObstacleX === 0 || 2048 - lastObstacleX > gap) { var obstacleX = 2048 + 100; var obstacleY = 2400; // Random obstacle type var obstacleType = Math.random() < 0.5 ? 'spike' : 'platform'; // Lower spike chance to 50% if (obstacleType === 'platform') { obstacleY = 2200 + Math.random() * 200; } var obstacle = new Obstacle(obstacleType, obstacleX, obstacleY); obstacles.push(obstacle); game.addChild(obstacle); lastObstacleX = obstacleX; } } function checkCollisions() { // Check orb collisions for (var i = orbs.length - 1; i >= 0; i--) { var orb = orbs[i]; if (!orb.collected && player.intersects(orb)) { orb.collected = true; player.hasPowerJump = true; player.showPowerOverlay(); powerOverlay = player.children[player.children.length - 1]; if (powerOverlay) { powerOverlay.visible = true; powerOverlay.alpha = 0.5; } // Flash player cyan to indicate power-up collected LK.effects.flashObject(player, 0x00ffff, 500); orb.destroy(); orbs.splice(i, 1); continue; } // Remove off-screen orbs if (orb.x < -100) { orb.destroy(); orbs.splice(i, 1); } } for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; if (player.intersects(obstacle)) { if (!player.isInvincible) { resetGame(); return; } // If invincible, ignore collision and continue } // Remove off-screen obstacles if (obstacle.x < -100) { obstacle.destroy(); obstacles.splice(i, 1); } } } // Touch controls game.down = function (x, y, obj) { if (!gameStarted) { startGame(); } player.jump(); }; // Update game game.update = function () { if (!gameStarted) return; // Update distance distance += gameSpeed; scoreText.setText('Distance: ' + Math.floor(distance / 10)); // Spawn obstacles spawnTimer++; if (spawnTimer % 45 === 0) { // Spawn every 45 ticks (~0.75 seconds) spawnObstacle(); } // Spawn orbs occasionally orbSpawnTimer++; if (orbSpawnTimer % 120 === 0) { // Spawn every 120 ticks (~2 seconds) spawnOrb(); } // Update obstacle positions for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; obstacle.x -= gameSpeed; // Track last obstacle position for gap calculation if (obstacle.x < 2048 && obstacle.x > lastObstacleX - 2048) { lastObstacleX = obstacle.x; } } // Update orb positions for (var i = 0; i < orbs.length; i++) { var orb = orbs[i]; orb.x -= gameSpeed; } // Check collisions checkCollisions(); // Increase difficulty gradually if (LK.ticks % 900 === 0) { // Every 15 seconds gameSpeed += 0.3; gameSpeed = Math.min(gameSpeed, 10); // Cap max speed } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Obstacle = Container.expand(function (type, x, y) {
var self = Container.call(this);
self.obstacleType = type || 'spike';
if (self.obstacleType === 'spike') {
var obstacleGraphics = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 1.0
});
} else if (self.obstacleType === 'platform') {
var obstacleGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.x = x || 0;
self.y = y || 0;
self.speed = -5;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Orb = Container.expand(function (x, y) {
var self = Container.call(this);
var orbGraphics = self.attachAsset('orb', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x || 0;
self.y = y || 0;
self.speed = -5;
self.collected = false;
self.update = function () {
self.x += self.speed;
// Gentle floating animation
orbGraphics.y = Math.sin(LK.ticks * 0.1) * 10;
// Gentle rotation
orbGraphics.rotation += 0.05;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.playerGraphics = playerGraphics; // Reference for icon switching
// Invincibility overlay (above player)
var invOverlay = self.attachAsset('Invincibility-overlay', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -60,
// above player, adjust as needed
visible: false,
alpha: 1
});
// Invincibility state and timer
self.isInvincible = false;
self.invincibleTicks = 0;
self.setInvincible = function (durationTicks) {
self.isInvincible = true;
self.invincibleTicks = durationTicks;
// Show overlay to indicate invincibility
if (powerOverlay) {
powerOverlay.visible = true;
powerOverlay.alpha = 0.7;
}
// Show invincibility overlay
if (invOverlay) {
invOverlay.visible = true;
}
};
self.clearInvincible = function () {
self.isInvincible = false;
self.invincibleTicks = 0;
if (powerOverlay) {
powerOverlay.visible = false;
powerOverlay.alpha = 0.5;
}
// Hide invincibility overlay
if (invOverlay) {
invOverlay.visible = false;
}
};
self.setIcon = function (iconId) {
// Remove old graphics
if (self.playerGraphics && self.playerGraphics.parent) {
self.playerGraphics.parent.removeChild(self.playerGraphics);
}
// Add new graphics
var newGfx = self.attachAsset(iconId, {
anchorX: 0.5,
anchorY: 0.5
});
self.playerGraphics = newGfx;
// Ensure player icon is always fully opaque
if (self.playerGraphics) {
self.playerGraphics.alpha = 1;
}
};
var powerOverlay = self.attachAsset('Orb_powerup_overlay_on_player', {
anchorX: 0.5,
anchorY: 0.5,
visible: false,
alpha: 0.5
});
self.velocityY = 0;
self.gravity = 0.8;
self.jumpPower = -18;
self.powerJumpPower = -28;
self.hasPowerJump = false;
self.isGrounded = false;
self.groundY = 2400;
self.jump = function () {
if (self.isGrounded) {
if (self.hasPowerJump) {
self.velocityY = self.powerJumpPower;
self.hasPowerJump = false;
// Fade out power overlay with tween
tween(powerOverlay, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
powerOverlay.visible = false;
powerOverlay.alpha = 0.5; // Reset alpha for next use
}
});
// Flash player blue to indicate power jump used
LK.effects.flashObject(self, 0x00ffff, 300);
// Ensure player icon is always fully opaque
if (self.playerGraphics) {
self.playerGraphics.alpha = 1;
}
} else {
self.velocityY = self.jumpPower;
}
self.isGrounded = false;
// Start spinning on jump
self.spinSpeed = 0.25; // Always spin right, or randomize for variety
LK.getSound('jump').play();
}
};
self.showPowerOverlay = function () {
powerOverlay.visible = true;
powerOverlay.alpha = 0.5;
// Ensure player icon is always fully opaque
if (self.playerGraphics) {
self.playerGraphics.alpha = 1;
}
};
self.hidePowerOverlay = function () {
powerOverlay.visible = false;
powerOverlay.alpha = 0.5; // Reset alpha for next use
// Ensure player icon is always fully opaque
if (self.playerGraphics) {
self.playerGraphics.alpha = 1;
}
};
self.update = function () {
// Invincibility timer tick down
if (self.isInvincible) {
if (self.invincibleTicks > 0) {
self.invincibleTicks--;
if (self.invincibleTicks === 0) {
self.clearInvincible();
}
}
// Ensure invincibility overlay is visible
if (invOverlay) invOverlay.visible = true;
} else {
// Ensure invincibility overlay is hidden
if (invOverlay) invOverlay.visible = false;
}
// Only show rainbow overlay (powerOverlay) if orb powerup is active
if (powerOverlay) {
if (self.hasPowerJump) {
powerOverlay.visible = true;
powerOverlay.alpha = 0.5;
} else {
powerOverlay.visible = false;
powerOverlay.alpha = 0.5;
}
}
// --- SPIN LOGIC START ---
if (typeof self.lastWasGrounded === "undefined") self.lastWasGrounded = self.isGrounded;
if (typeof self.spinSpeed === "undefined") self.spinSpeed = 0;
if (typeof self.currentRotation === "undefined") self.currentRotation = 0;
// If airborne, spin
if (!self.isGrounded) {
// Spin direction: positive for right, negative for left (could be random or based on last jump, here always right)
if (self.spinSpeed === 0) {
// Start spinning with a default speed if just left ground
self.spinSpeed = 0.25;
}
self.currentRotation += self.spinSpeed;
if (self.playerGraphics) self.playerGraphics.rotation = self.currentRotation;
} else {
// On ground, stop spinning but keep rotation
if (!self.lastWasGrounded) {
// Just landed, keep rotation and stop spin
self.spinSpeed = 0;
if (self.playerGraphics) self.playerGraphics.rotation = self.currentRotation;
}
}
// Track last grounded state for transition
self.lastWasGrounded = self.isGrounded;
// --- SPIN LOGIC END ---
// Apply gravity
self.velocityY += self.gravity;
self.y += self.velocityY;
// Ground collision
if (self.y >= self.groundY) {
self.y = self.groundY;
self.velocityY = 0;
self.isGrounded = true;
}
// Screen bounds
if (self.y < 0) {
self.y = 0;
self.velocityY = 0;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
var player;
var obstacles = [];
var orbs = [];
var gameSpeed = 5;
var spawnTimer = 0;
var orbSpawnTimer = 0;
var distance = 0;
var gameStarted = false;
var lastObstacleX = 0;
// Background
var bg = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create player
player = game.addChild(new Player());
player.x = 300;
player.y = 2400;
player.groundY = 2400;
// Score display
var scoreText = new Text2('Distance: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreText);
// Icon kit button (top right, 100x100 safe zone)
var iconKitBtn = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: -60,
y: 60,
scaleX: 0.7,
scaleY: 0.7
});
iconKitBtn.interactive = true;
iconKitBtn.buttonMode = true;
LK.gui.topRight.addChild(iconKitBtn);
// Icon selection overlay (hidden by default)
var iconOverlayBg = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
iconOverlayBg.alpha = 0.7;
iconOverlayBg.visible = false;
var iconChoices = [];
var iconIds = ['player', 'Icon2', 'Icon3', 'Icon4'];
var iconSelectedIndex = 0; // 0 = default
for (var i = 0; i < 4; i++) {
var icon = LK.getAsset(iconIds[i], {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + (i - 1.5) * 220,
y: 2732 / 2,
scaleX: 1.5,
scaleY: 1.5
});
icon.visible = false;
icon.interactive = true;
icon.buttonMode = true;
icon.iconIndex = i;
iconChoices.push(icon);
}
function showIconOverlay() {
iconOverlayBg.visible = true;
for (var i = 0; i < iconChoices.length; i++) {
iconChoices[i].visible = true;
}
// Make player invincible while overlay is open (very long duration, will be cleared on hide)
if (player && player.setInvincible) {
player.setInvincible(999999); // Effectively infinite until overlay is closed
}
// Game is automatically paused by LK when overlays are shown
}
function hideIconOverlay() {
iconOverlayBg.visible = false;
for (var i = 0; i < iconChoices.length; i++) {
iconChoices[i].visible = false;
}
// Grant 5 seconds (300 ticks) invincibility after overlay closes
if (player && player.setInvincible) {
player.setInvincible(300);
}
// Game is automatically resumed by LK when overlays are hidden
}
// Add overlay and icons to game (above everything)
game.addChild(iconOverlayBg);
for (var i = 0; i < iconChoices.length; i++) {
game.addChild(iconChoices[i]);
}
// Instructions
var instructionText = new Text2('TAP TO JUMP', {
size: 80,
fill: 0xFFFF00
});
instructionText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionText);
// Icon kit button event
iconKitBtn.down = function (x, y, obj) {
if (!iconOverlayBg.visible) {
showIconOverlay();
}
};
// Icon selection events
for (var i = 0; i < iconChoices.length; i++) {
iconChoices[i].down = function (x, y, obj) {
var idx = this.iconIndex;
iconSelectedIndex = idx;
// Change player icon
if (player && player.setIcon) {
player.setIcon(iconIds[idx]);
}
hideIconOverlay();
};
}
// Hide overlay if background is tapped
iconOverlayBg.down = function (x, y, obj) {
hideIconOverlay();
};
function startGame() {
if (!gameStarted) {
gameStarted = true;
instructionText.visible = false;
LK.playMusic('bgMusic');
}
}
function resetGame() {
// Reset player
if (player && player.setIcon && typeof iconSelectedIndex !== "undefined" && typeof iconIds !== "undefined") {
player.setIcon(iconIds[iconSelectedIndex]);
}
player.x = 300;
player.y = 2400;
player.velocityY = 0;
player.isGrounded = true;
// Reset spin state
player.spinSpeed = 0;
player.currentRotation = 0;
if (player.playerGraphics) player.playerGraphics.rotation = 0;
// Clear obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
}
obstacles = [];
// Clear orbs
for (var i = orbs.length - 1; i >= 0; i--) {
orbs[i].destroy();
}
orbs = [];
// Reset player power jump
player.hasPowerJump = false;
// Hide power overlay
player.hidePowerOverlay();
// Reset game state
distance = 0;
spawnTimer = 0;
lastObstacleX = 0;
gameStarted = false;
instructionText.visible = true;
// Flash effect
LK.effects.flashScreen(0xff0000, 500);
LK.getSound('death').play();
}
function spawnOrb() {
var orbX = 2048 + 100;
var orbY = 2000 + Math.random() * 400; // Random height between ground and air
var orb = new Orb(orbX, orbY);
orbs.push(orb);
game.addChild(orb);
}
function spawnObstacle() {
var minGap = 300;
var maxGap = 500;
var gap = minGap + Math.random() * (maxGap - minGap);
if (lastObstacleX === 0 || 2048 - lastObstacleX > gap) {
var obstacleX = 2048 + 100;
var obstacleY = 2400;
// Random obstacle type
var obstacleType = Math.random() < 0.5 ? 'spike' : 'platform'; // Lower spike chance to 50%
if (obstacleType === 'platform') {
obstacleY = 2200 + Math.random() * 200;
}
var obstacle = new Obstacle(obstacleType, obstacleX, obstacleY);
obstacles.push(obstacle);
game.addChild(obstacle);
lastObstacleX = obstacleX;
}
}
function checkCollisions() {
// Check orb collisions
for (var i = orbs.length - 1; i >= 0; i--) {
var orb = orbs[i];
if (!orb.collected && player.intersects(orb)) {
orb.collected = true;
player.hasPowerJump = true;
player.showPowerOverlay();
powerOverlay = player.children[player.children.length - 1];
if (powerOverlay) {
powerOverlay.visible = true;
powerOverlay.alpha = 0.5;
}
// Flash player cyan to indicate power-up collected
LK.effects.flashObject(player, 0x00ffff, 500);
orb.destroy();
orbs.splice(i, 1);
continue;
}
// Remove off-screen orbs
if (orb.x < -100) {
orb.destroy();
orbs.splice(i, 1);
}
}
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (player.intersects(obstacle)) {
if (!player.isInvincible) {
resetGame();
return;
}
// If invincible, ignore collision and continue
}
// Remove off-screen obstacles
if (obstacle.x < -100) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
}
// Touch controls
game.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
}
player.jump();
};
// Update game
game.update = function () {
if (!gameStarted) return;
// Update distance
distance += gameSpeed;
scoreText.setText('Distance: ' + Math.floor(distance / 10));
// Spawn obstacles
spawnTimer++;
if (spawnTimer % 45 === 0) {
// Spawn every 45 ticks (~0.75 seconds)
spawnObstacle();
}
// Spawn orbs occasionally
orbSpawnTimer++;
if (orbSpawnTimer % 120 === 0) {
// Spawn every 120 ticks (~2 seconds)
spawnOrb();
}
// Update obstacle positions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
obstacle.x -= gameSpeed;
// Track last obstacle position for gap calculation
if (obstacle.x < 2048 && obstacle.x > lastObstacleX - 2048) {
lastObstacleX = obstacle.x;
}
}
// Update orb positions
for (var i = 0; i < orbs.length; i++) {
var orb = orbs[i];
orb.x -= gameSpeed;
}
// Check collisions
checkCollisions();
// Increase difficulty gradually
if (LK.ticks % 900 === 0) {
// Every 15 seconds
gameSpeed += 0.3;
gameSpeed = Math.min(gameSpeed, 10); // Cap max speed
}
};