/****
* 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();
};