/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, currentLevel: 1 }); /**** * Classes ****/ var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); self.velX = (Math.random() - 0.5) * 10; self.velY = (Math.random() - 0.5) * 10 - 5; self.gravity = 0.3; self.life = 30 + Math.random() * 30; self.maxLife = self.life; self.update = function () { self.velY += self.gravity; self.x += self.velX; self.y += self.velY; self.life--; self.alpha = self.life / self.maxLife; if (self.life <= 0) { self.destroy(); var index = particles.indexOf(self); if (index !== -1) { particles.splice(index, 1); } } }; return self; }); var Platform = Container.expand(function () { var self = Container.call(this); var platformGraphics = self.attachAsset('platform', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 5; self.active = true; self.verticalMovement = false; self.verticalDirection = 1; self.verticalSpeed = 2; self.startY = 0; // Make level 2+ platforms different if (storage.currentLevel >= 2) { platformGraphics.tint = 0x3498db; // Blue platforms for level 2+ self.verticalMovement = Math.random() > 0.5; // 50% chance of vertical movement } self.update = function () { if (!self.active) { return; } self.x -= self.speed; // Level 2+ platforms can move vertically if (self.verticalMovement && storage.currentLevel >= 2) { // Store initial Y position if not already set if (self.startY === 0) { self.startY = self.y; } // Move platform up and down within a range self.y += self.verticalDirection * self.verticalSpeed; // Change direction when reached limits if (self.y > self.startY + 150 || self.y < self.startY - 150) { self.verticalDirection *= -1; } } // If platform is off-screen to the left, deactivate it if (self.x < -platformGraphics.width) { self.active = false; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.gravity = 0.6; self.jumpForce = -19; self.velocity = 0; self.isJumping = false; self.isDead = false; self.isOnGround = false; self.jump = function () { if (self.isOnGround && !self.isDead) { self.velocity = self.jumpForce; self.isJumping = true; self.isOnGround = false; // Play jump sound with proper volume LK.getSound('jump').play({ volume: 0.7 }); self.createJumpEffect(); // Add a small boost at the peak of jump for better spike dodging LK.setTimeout(function () { if (self.isJumping && !self.isDead && self.velocity > -2 && self.velocity < 2) { // Small horizontal push tween(self, { x: self.x + 20 }, { duration: 300, easing: tween.easeOut }); } }, 300); } }; self.createJumpEffect = function () { for (var i = 0; i < 5; i++) { var particle = new Particle(); particle.x = self.x; particle.y = self.y + 30; game.addChild(particle); particles.push(particle); } }; self.die = function () { if (!self.isDead) { self.isDead = true; // Make sure the current level is saved before game over // storage plugin uses direct property assignment for persistence storage.currentLevel = storage.currentLevel; // This persists the current level // Play death sound with proper volume LK.getSound('death').play({ volume: 0.8 }); LK.stopMusic(); LK.effects.flashObject(self, 0xff0000, 500); LK.effects.flashScreen(0xff0000, 300); // Create death particles for (var i = 0; i < 15; i++) { var particle = new Particle(); particle.x = self.x; particle.y = self.y; game.addChild(particle); particles.push(particle); } LK.setTimeout(function () { LK.showGameOver(); }, 1000); } }; self.update = function () { if (self.isDead) { return; } // Apply gravity self.velocity += self.gravity; self.y += self.velocity; // Check ground collision if (self.y >= groundY - playerGraphics.height / 2) { self.y = groundY - playerGraphics.height / 2; self.velocity = 0; self.isJumping = false; self.isOnGround = true; } // Check ceiling collision if (self.y <= ceilingY + playerGraphics.height / 2) { self.y = ceilingY + playerGraphics.height / 2; self.velocity = 0; } // Rotate player based on movement if (self.isJumping) { playerGraphics.rotation += 0.1; } else { // Gradually reset rotation when on ground playerGraphics.rotation = playerGraphics.rotation % (Math.PI * 2); if (playerGraphics.rotation > 0.1) { playerGraphics.rotation -= 0.1; } else if (playerGraphics.rotation < -0.1) { playerGraphics.rotation += 0.1; } else { playerGraphics.rotation = 0; } } }; return self; }); var Spike = Container.expand(function () { var self = Container.call(this); var spikeGraphics = self.attachAsset('spike', { anchorX: 0.5, anchorY: 0.5 }); self.rotation = Math.PI / 4; // Rotate to make it look like a spike self.speed = 5; self.active = true; // Check if we're in level 2+ and make the spike different if (storage.currentLevel >= 2) { spikeGraphics.tint = 0xf1c40f; // Yellow spikes for level 2+ self.scaleX = 1.2; // Slightly larger spikes self.scaleY = 1.2; } self.update = function () { if (!self.active) { return; } // Store the last x position to detect when passing the player if (self.lastX === undefined) { self.lastX = self.x; self.passed = false; } self.x -= self.speed; // If spike is off-screen to the left, deactivate it if (self.x < -50) { self.active = false; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // Game variables var player; var obstacles = []; var platforms = []; var particles = []; var groundY = 2500; var ceilingY = 200; var score = 0; var obstacleTimer = 0; var obstacleInterval = 90; // Frames between obstacle spawns var platformTimer = 0; var platformInterval = 180; // Frames between platform spawns var difficultyTimer = 0; var difficultyInterval = 600; // Frames before increasing difficulty var gameSpeed = 5; var maxGameSpeed = 12; var isGameStarted = false; var distanceTraveled = 0; var passedObstacles = []; // Track which obstacles have been passed // Create score text var scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create level text var levelTxt = new Text2('Level 1', { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); levelTxt.y = 120; LK.gui.top.addChild(levelTxt); // Create ground var ground = game.addChild(LK.getAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: groundY })); // Create ceiling var ceiling = game.addChild(LK.getAsset('ceiling', { anchorX: 0, anchorY: 0, x: 0, y: ceilingY - 40 })); // Create player player = new Player(); player.x = 400; player.y = groundY - 100; game.addChild(player); // Create instructions text var instructionsTxt = new Text2('Tap to jump and avoid spikes!', { size: 80, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 0.5); instructionsTxt.x = 2048 / 2; instructionsTxt.y = 2732 / 2; game.addChild(instructionsTxt); // Create tap to start text var startTxt = new Text2('Tap to Start', { size: 120, fill: 0xFFFFFF }); startTxt.anchor.set(0.5, 0.5); startTxt.x = 2048 / 2; startTxt.y = 2732 / 2 + 200; game.addChild(startTxt); // Handle user input game.down = function (x, y, obj) { if (!isGameStarted) { startGame(); } else if (!player.isDead) { player.jump(); } }; function startGame() { isGameStarted = true; instructionsTxt.visible = false; startTxt.visible = false; // Reset score but keep the current level from storage score = 0; updateScore(0); // Make sure we use the stored level that persists through game resets if (!storage.currentLevel || storage.currentLevel < 1) { storage.currentLevel = 1; } updateLevel(storage.currentLevel); // Play background music LK.playMusic('gameMusic', { volume: 0.6, fade: { start: 0, end: 1, duration: 1000 } }); } function createSpike() { var spike = new Spike(); spike.x = 2100; spike.y = groundY - spike.height / 2; game.addChild(spike); obstacles.push(spike); } function createPlatform() { var platform = new Platform(); platform.x = 2100; // Random y position but ensure it's not too close to ground or ceiling var minY = ceilingY + 200; var maxY = groundY - 200; platform.y = minY + Math.random() * (maxY - minY); game.addChild(platform); platforms.push(platform); } function updateScore(value) { score = value; scoreTxt.setText('Score: ' + score); LK.setScore(score); // Update high score if needed if (score > storage.highScore) { storage.highScore = score; } // For visual effect when score increases significantly if (value % 50 === 0) { // Add particle effects to celebrate milestones for (var i = 0; i < 10; i++) { var particle = new Particle(); particle.x = scoreTxt.x; particle.y = scoreTxt.y; game.addChild(particle); particles.push(particle); } } } function updateLevel(level) { storage.currentLevel = level; levelTxt.setText('Level ' + level); // Make gameplay different for level 2 if (level === 2) { // Change the player's appearance for level 2 player.getChildAt(0).tint = 0xe74c3c; // Red player in level 2 // Make level 2 more challenging obstacleInterval = 60; // More frequent obstacles platformInterval = 120; // More frequent platforms gameSpeed = 7; // Faster game speed // Increase jump force for higher jumps in level 2 player.jumpForce = -22; // Create initial level 2 obstacles for (var i = 0; i < 3; i++) { var spike = new Spike(); spike.x = 2100 + i * 500; spike.y = groundY - spike.height / 2; game.addChild(spike); obstacles.push(spike); } } else { // Adjust difficulty based on level for other levels obstacleInterval = Math.max(30, 90 - (level - 1) * 10); platformInterval = Math.max(60, 180 - (level - 1) * 20); gameSpeed = Math.min(maxGameSpeed, 5 + (level - 1) * 0.5); } // Update obstacle speeds obstacles.forEach(function (obstacle) { if (obstacle.active) { obstacle.speed = gameSpeed; } }); // Update platform speeds platforms.forEach(function (platform) { if (platform.active) { platform.speed = gameSpeed; } }); } function checkCollisions() { if (player.isDead) { return; } // Check spike collisions for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; if (obstacle.active && player.intersects(obstacle)) { player.die(); return; } } // Check platform collisions var wasOnPlatform = false; for (var j = 0; j < platforms.length; j++) { var platform = platforms[j]; if (platform.active && player.intersects(platform)) { // Only if player is falling and above the platform if (player.velocity > 0 && player.y < platform.y - platform.height / 2) { player.y = platform.y - platform.height / 2 - player.height / 2; player.velocity = 0; player.isJumping = false; player.isOnGround = true; wasOnPlatform = true; } } } // If not on a platform and not on the ground, player is in the air if (!wasOnPlatform && player.y < groundY - player.height / 2) { player.isOnGround = false; } } function clearInactiveObjects() { // Clear inactive obstacles for (var i = obstacles.length - 1; i >= 0; i--) { if (!obstacles[i].active) { obstacles[i].destroy(); obstacles.splice(i, 1); } } // Clear inactive platforms for (var j = platforms.length - 1; j >= 0; j--) { if (!platforms[j].active) { platforms[j].destroy(); platforms.splice(j, 1); } } } function levelComplete() { // Play level complete sound with proper volume LK.getSound('levelComplete').play({ volume: 0.9 }); LK.effects.flashScreen(0x27ae60, 500); var levelCompleteTxt = new Text2('LEVEL COMPLETE!', { size: 120, fill: 0xFFFFFF }); levelCompleteTxt.anchor.set(0.5, 0.5); levelCompleteTxt.x = 2048 / 2; levelCompleteTxt.y = 2732 / 2; game.addChild(levelCompleteTxt); // Clear current obstacles and platforms if moving to level 2 if (storage.currentLevel === 1 && score >= 10) { // Clear obstacles for (var i = obstacles.length - 1; i >= 0; i--) { obstacles[i].destroy(); obstacles.splice(i, 1); } // Clear platforms for (var j = platforms.length - 1; j >= 0; j--) { platforms[j].destroy(); platforms.splice(j, 1); } // Change game environment for level 2 ground.tint = 0x8e44ad; // Purple ground for level 2 ceiling.tint = 0x8e44ad; // Purple ceiling for level 2 game.setBackgroundColor(0x2c3e50); // Darker background for level 2 } else { // Keep obstacles and platforms but increase their speed // This ensures continuous gameplay rather than resetting obstacles.forEach(function (obstacle) { if (obstacle.active) { obstacle.speed = Math.min(maxGameSpeed, obstacle.speed + 0.5); } }); platforms.forEach(function (platform) { if (platform.active) { platform.speed = Math.min(maxGameSpeed, platform.speed + 0.5); } }); } // Don't reset player position, let them continue playing // Advance to next level after a short delay LK.setTimeout(function () { levelCompleteTxt.destroy(); updateLevel(storage.currentLevel + 1); }, 2000); } // Main game update loop game.update = function () { if (!isGameStarted || player.isDead) { return; } // Increase distance traveled distanceTraveled += gameSpeed; // Check for obstacles that player has passed for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; if (obstacle.active && !obstacle.passed && obstacle.x < player.x && obstacle.lastX >= player.x) { obstacle.passed = true; updateScore(score + 1); // Increase score by 1 when passing a spike LK.effects.flashObject(player, 0x00ff00, 200); // Visual feedback } // Update lastX after checking obstacle.lastX = obstacle.x; } // Remove automatic score increase based on distance traveled // No longer increasing score just for traveling distance // Check for level progression at score 10 if (score === 10 && storage.currentLevel === 1) { levelComplete(); } else if (score > 10 && score % 100 === 0) { // For later levels, progress every 100 points // Only trigger once when exactly hitting the target if (score % 200 !== 0) { levelComplete(); } } // Spawn new obstacles obstacleTimer++; if (obstacleTimer >= obstacleInterval) { createSpike(); obstacleTimer = 0; } // Spawn new platforms platformTimer++; if (platformTimer >= platformInterval) { createPlatform(); platformTimer = 0; } // Increase difficulty over time difficultyTimer++; if (difficultyTimer >= difficultyInterval) { gameSpeed = Math.min(maxGameSpeed, gameSpeed + 0.1); difficultyTimer = 0; } // Update obstacles for (var i = 0; i < obstacles.length; i++) { obstacles[i].update(); } // Update platforms for (var j = 0; j < platforms.length; j++) { platforms[j].update(); } // Update particles for (var k = 0; k < particles.length; k++) { particles[k].update(); } // Update player player.update(); // Check collisions checkCollisions(); // Clean up inactive objects clearInactiveObjects(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
currentLevel: 1
});
/****
* Classes
****/
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.velX = (Math.random() - 0.5) * 10;
self.velY = (Math.random() - 0.5) * 10 - 5;
self.gravity = 0.3;
self.life = 30 + Math.random() * 30;
self.maxLife = self.life;
self.update = function () {
self.velY += self.gravity;
self.x += self.velX;
self.y += self.velY;
self.life--;
self.alpha = self.life / self.maxLife;
if (self.life <= 0) {
self.destroy();
var index = particles.indexOf(self);
if (index !== -1) {
particles.splice(index, 1);
}
}
};
return self;
});
var Platform = Container.expand(function () {
var self = Container.call(this);
var platformGraphics = self.attachAsset('platform', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.active = true;
self.verticalMovement = false;
self.verticalDirection = 1;
self.verticalSpeed = 2;
self.startY = 0;
// Make level 2+ platforms different
if (storage.currentLevel >= 2) {
platformGraphics.tint = 0x3498db; // Blue platforms for level 2+
self.verticalMovement = Math.random() > 0.5; // 50% chance of vertical movement
}
self.update = function () {
if (!self.active) {
return;
}
self.x -= self.speed;
// Level 2+ platforms can move vertically
if (self.verticalMovement && storage.currentLevel >= 2) {
// Store initial Y position if not already set
if (self.startY === 0) {
self.startY = self.y;
}
// Move platform up and down within a range
self.y += self.verticalDirection * self.verticalSpeed;
// Change direction when reached limits
if (self.y > self.startY + 150 || self.y < self.startY - 150) {
self.verticalDirection *= -1;
}
}
// If platform is off-screen to the left, deactivate it
if (self.x < -platformGraphics.width) {
self.active = false;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.gravity = 0.6;
self.jumpForce = -19;
self.velocity = 0;
self.isJumping = false;
self.isDead = false;
self.isOnGround = false;
self.jump = function () {
if (self.isOnGround && !self.isDead) {
self.velocity = self.jumpForce;
self.isJumping = true;
self.isOnGround = false;
// Play jump sound with proper volume
LK.getSound('jump').play({
volume: 0.7
});
self.createJumpEffect();
// Add a small boost at the peak of jump for better spike dodging
LK.setTimeout(function () {
if (self.isJumping && !self.isDead && self.velocity > -2 && self.velocity < 2) {
// Small horizontal push
tween(self, {
x: self.x + 20
}, {
duration: 300,
easing: tween.easeOut
});
}
}, 300);
}
};
self.createJumpEffect = function () {
for (var i = 0; i < 5; i++) {
var particle = new Particle();
particle.x = self.x;
particle.y = self.y + 30;
game.addChild(particle);
particles.push(particle);
}
};
self.die = function () {
if (!self.isDead) {
self.isDead = true;
// Make sure the current level is saved before game over
// storage plugin uses direct property assignment for persistence
storage.currentLevel = storage.currentLevel; // This persists the current level
// Play death sound with proper volume
LK.getSound('death').play({
volume: 0.8
});
LK.stopMusic();
LK.effects.flashObject(self, 0xff0000, 500);
LK.effects.flashScreen(0xff0000, 300);
// Create death particles
for (var i = 0; i < 15; i++) {
var particle = new Particle();
particle.x = self.x;
particle.y = self.y;
game.addChild(particle);
particles.push(particle);
}
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
};
self.update = function () {
if (self.isDead) {
return;
}
// Apply gravity
self.velocity += self.gravity;
self.y += self.velocity;
// Check ground collision
if (self.y >= groundY - playerGraphics.height / 2) {
self.y = groundY - playerGraphics.height / 2;
self.velocity = 0;
self.isJumping = false;
self.isOnGround = true;
}
// Check ceiling collision
if (self.y <= ceilingY + playerGraphics.height / 2) {
self.y = ceilingY + playerGraphics.height / 2;
self.velocity = 0;
}
// Rotate player based on movement
if (self.isJumping) {
playerGraphics.rotation += 0.1;
} else {
// Gradually reset rotation when on ground
playerGraphics.rotation = playerGraphics.rotation % (Math.PI * 2);
if (playerGraphics.rotation > 0.1) {
playerGraphics.rotation -= 0.1;
} else if (playerGraphics.rotation < -0.1) {
playerGraphics.rotation += 0.1;
} else {
playerGraphics.rotation = 0;
}
}
};
return self;
});
var Spike = Container.expand(function () {
var self = Container.call(this);
var spikeGraphics = self.attachAsset('spike', {
anchorX: 0.5,
anchorY: 0.5
});
self.rotation = Math.PI / 4; // Rotate to make it look like a spike
self.speed = 5;
self.active = true;
// Check if we're in level 2+ and make the spike different
if (storage.currentLevel >= 2) {
spikeGraphics.tint = 0xf1c40f; // Yellow spikes for level 2+
self.scaleX = 1.2; // Slightly larger spikes
self.scaleY = 1.2;
}
self.update = function () {
if (!self.active) {
return;
}
// Store the last x position to detect when passing the player
if (self.lastX === undefined) {
self.lastX = self.x;
self.passed = false;
}
self.x -= self.speed;
// If spike is off-screen to the left, deactivate it
if (self.x < -50) {
self.active = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// Game variables
var player;
var obstacles = [];
var platforms = [];
var particles = [];
var groundY = 2500;
var ceilingY = 200;
var score = 0;
var obstacleTimer = 0;
var obstacleInterval = 90; // Frames between obstacle spawns
var platformTimer = 0;
var platformInterval = 180; // Frames between platform spawns
var difficultyTimer = 0;
var difficultyInterval = 600; // Frames before increasing difficulty
var gameSpeed = 5;
var maxGameSpeed = 12;
var isGameStarted = false;
var distanceTraveled = 0;
var passedObstacles = []; // Track which obstacles have been passed
// Create score text
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create level text
var levelTxt = new Text2('Level 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
levelTxt.y = 120;
LK.gui.top.addChild(levelTxt);
// Create ground
var ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: groundY
}));
// Create ceiling
var ceiling = game.addChild(LK.getAsset('ceiling', {
anchorX: 0,
anchorY: 0,
x: 0,
y: ceilingY - 40
}));
// Create player
player = new Player();
player.x = 400;
player.y = groundY - 100;
game.addChild(player);
// Create instructions text
var instructionsTxt = new Text2('Tap to jump and avoid spikes!', {
size: 80,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
instructionsTxt.x = 2048 / 2;
instructionsTxt.y = 2732 / 2;
game.addChild(instructionsTxt);
// Create tap to start text
var startTxt = new Text2('Tap to Start', {
size: 120,
fill: 0xFFFFFF
});
startTxt.anchor.set(0.5, 0.5);
startTxt.x = 2048 / 2;
startTxt.y = 2732 / 2 + 200;
game.addChild(startTxt);
// Handle user input
game.down = function (x, y, obj) {
if (!isGameStarted) {
startGame();
} else if (!player.isDead) {
player.jump();
}
};
function startGame() {
isGameStarted = true;
instructionsTxt.visible = false;
startTxt.visible = false;
// Reset score but keep the current level from storage
score = 0;
updateScore(0);
// Make sure we use the stored level that persists through game resets
if (!storage.currentLevel || storage.currentLevel < 1) {
storage.currentLevel = 1;
}
updateLevel(storage.currentLevel);
// Play background music
LK.playMusic('gameMusic', {
volume: 0.6,
fade: {
start: 0,
end: 1,
duration: 1000
}
});
}
function createSpike() {
var spike = new Spike();
spike.x = 2100;
spike.y = groundY - spike.height / 2;
game.addChild(spike);
obstacles.push(spike);
}
function createPlatform() {
var platform = new Platform();
platform.x = 2100;
// Random y position but ensure it's not too close to ground or ceiling
var minY = ceilingY + 200;
var maxY = groundY - 200;
platform.y = minY + Math.random() * (maxY - minY);
game.addChild(platform);
platforms.push(platform);
}
function updateScore(value) {
score = value;
scoreTxt.setText('Score: ' + score);
LK.setScore(score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// For visual effect when score increases significantly
if (value % 50 === 0) {
// Add particle effects to celebrate milestones
for (var i = 0; i < 10; i++) {
var particle = new Particle();
particle.x = scoreTxt.x;
particle.y = scoreTxt.y;
game.addChild(particle);
particles.push(particle);
}
}
}
function updateLevel(level) {
storage.currentLevel = level;
levelTxt.setText('Level ' + level);
// Make gameplay different for level 2
if (level === 2) {
// Change the player's appearance for level 2
player.getChildAt(0).tint = 0xe74c3c; // Red player in level 2
// Make level 2 more challenging
obstacleInterval = 60; // More frequent obstacles
platformInterval = 120; // More frequent platforms
gameSpeed = 7; // Faster game speed
// Increase jump force for higher jumps in level 2
player.jumpForce = -22;
// Create initial level 2 obstacles
for (var i = 0; i < 3; i++) {
var spike = new Spike();
spike.x = 2100 + i * 500;
spike.y = groundY - spike.height / 2;
game.addChild(spike);
obstacles.push(spike);
}
} else {
// Adjust difficulty based on level for other levels
obstacleInterval = Math.max(30, 90 - (level - 1) * 10);
platformInterval = Math.max(60, 180 - (level - 1) * 20);
gameSpeed = Math.min(maxGameSpeed, 5 + (level - 1) * 0.5);
}
// Update obstacle speeds
obstacles.forEach(function (obstacle) {
if (obstacle.active) {
obstacle.speed = gameSpeed;
}
});
// Update platform speeds
platforms.forEach(function (platform) {
if (platform.active) {
platform.speed = gameSpeed;
}
});
}
function checkCollisions() {
if (player.isDead) {
return;
}
// Check spike collisions
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (obstacle.active && player.intersects(obstacle)) {
player.die();
return;
}
}
// Check platform collisions
var wasOnPlatform = false;
for (var j = 0; j < platforms.length; j++) {
var platform = platforms[j];
if (platform.active && player.intersects(platform)) {
// Only if player is falling and above the platform
if (player.velocity > 0 && player.y < platform.y - platform.height / 2) {
player.y = platform.y - platform.height / 2 - player.height / 2;
player.velocity = 0;
player.isJumping = false;
player.isOnGround = true;
wasOnPlatform = true;
}
}
}
// If not on a platform and not on the ground, player is in the air
if (!wasOnPlatform && player.y < groundY - player.height / 2) {
player.isOnGround = false;
}
}
function clearInactiveObjects() {
// Clear inactive obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
if (!obstacles[i].active) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
}
// Clear inactive platforms
for (var j = platforms.length - 1; j >= 0; j--) {
if (!platforms[j].active) {
platforms[j].destroy();
platforms.splice(j, 1);
}
}
}
function levelComplete() {
// Play level complete sound with proper volume
LK.getSound('levelComplete').play({
volume: 0.9
});
LK.effects.flashScreen(0x27ae60, 500);
var levelCompleteTxt = new Text2('LEVEL COMPLETE!', {
size: 120,
fill: 0xFFFFFF
});
levelCompleteTxt.anchor.set(0.5, 0.5);
levelCompleteTxt.x = 2048 / 2;
levelCompleteTxt.y = 2732 / 2;
game.addChild(levelCompleteTxt);
// Clear current obstacles and platforms if moving to level 2
if (storage.currentLevel === 1 && score >= 10) {
// Clear obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
// Clear platforms
for (var j = platforms.length - 1; j >= 0; j--) {
platforms[j].destroy();
platforms.splice(j, 1);
}
// Change game environment for level 2
ground.tint = 0x8e44ad; // Purple ground for level 2
ceiling.tint = 0x8e44ad; // Purple ceiling for level 2
game.setBackgroundColor(0x2c3e50); // Darker background for level 2
} else {
// Keep obstacles and platforms but increase their speed
// This ensures continuous gameplay rather than resetting
obstacles.forEach(function (obstacle) {
if (obstacle.active) {
obstacle.speed = Math.min(maxGameSpeed, obstacle.speed + 0.5);
}
});
platforms.forEach(function (platform) {
if (platform.active) {
platform.speed = Math.min(maxGameSpeed, platform.speed + 0.5);
}
});
}
// Don't reset player position, let them continue playing
// Advance to next level after a short delay
LK.setTimeout(function () {
levelCompleteTxt.destroy();
updateLevel(storage.currentLevel + 1);
}, 2000);
}
// Main game update loop
game.update = function () {
if (!isGameStarted || player.isDead) {
return;
}
// Increase distance traveled
distanceTraveled += gameSpeed;
// Check for obstacles that player has passed
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
if (obstacle.active && !obstacle.passed && obstacle.x < player.x && obstacle.lastX >= player.x) {
obstacle.passed = true;
updateScore(score + 1); // Increase score by 1 when passing a spike
LK.effects.flashObject(player, 0x00ff00, 200); // Visual feedback
}
// Update lastX after checking
obstacle.lastX = obstacle.x;
}
// Remove automatic score increase based on distance traveled
// No longer increasing score just for traveling distance
// Check for level progression at score 10
if (score === 10 && storage.currentLevel === 1) {
levelComplete();
} else if (score > 10 && score % 100 === 0) {
// For later levels, progress every 100 points
// Only trigger once when exactly hitting the target
if (score % 200 !== 0) {
levelComplete();
}
}
// Spawn new obstacles
obstacleTimer++;
if (obstacleTimer >= obstacleInterval) {
createSpike();
obstacleTimer = 0;
}
// Spawn new platforms
platformTimer++;
if (platformTimer >= platformInterval) {
createPlatform();
platformTimer = 0;
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer >= difficultyInterval) {
gameSpeed = Math.min(maxGameSpeed, gameSpeed + 0.1);
difficultyTimer = 0;
}
// Update obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
// Update platforms
for (var j = 0; j < platforms.length; j++) {
platforms[j].update();
}
// Update particles
for (var k = 0; k < particles.length; k++) {
particles[k].update();
}
// Update player
player.update();
// Check collisions
checkCollisions();
// Clean up inactive objects
clearInactiveObjects();
};