/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScores: []
});
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
// Create coin visual
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.collected = false;
self.rotation = 0;
// Animate the coin
self.update = function () {
self.x -= self.speed;
self.rotation += 0.05;
coinGraphics.rotation = self.rotation;
};
// Flash and mark as collected
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.effects.flashObject(self, 0xffff00, 300);
// Fade out and shrink
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
}
};
return self;
});
var Leaderboard = Container.expand(function () {
var self = Container.call(this);
// Create title text
var titleText = new Text2('HIGH SCORES', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = 50;
self.addChild(titleText);
// Array to hold score text objects
self.scoreTexts = [];
// Method to update the displayed scores
self.updateScores = function (scores) {
// Remove existing score texts
for (var i = 0; i < self.scoreTexts.length; i++) {
self.scoreTexts[i].destroy();
}
self.scoreTexts = [];
// Create new score texts
var maxToShow = Math.min(5, scores.length);
for (var i = 0; i < maxToShow; i++) {
var scoreText = new Text2(i + 1 + ". " + scores[i], {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.y = 150 + i * 80;
self.addChild(scoreText);
self.scoreTexts.push(scoreText);
}
// If no scores yet, show a message
if (scores.length === 0) {
var noScoreText = new Text2("No scores yet!", {
size: 60,
fill: 0xFFFFFF
});
noScoreText.anchor.set(0.5, 0);
noScoreText.y = 150;
self.addChild(noScoreText);
self.scoreTexts.push(noScoreText);
}
};
// Create back button
var backText = new Text2("BACK TO GAME", {
size: 60,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0);
backText.y = 600;
backText.interactive = true;
// Handle back button click
backText.down = function () {
self.visible = false;
};
self.addChild(backText);
return self;
});
var Pipe = Container.expand(function () {
var self = Container.call(this);
// Each pipe consists of top and bottom segments
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.5
});
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0.0,
scaleX: 1.5
});
self.speed = 5;
self.gapHeight = 450; // Increased gap height
self.scored = false;
self.setGapPosition = function (gapY) {
topPipe.y = gapY - self.gapHeight / 2;
bottomPipe.y = gapY + self.gapHeight / 2;
};
self.update = function () {
self.x -= self.speed;
};
self.getTopPipe = function () {
return topPipe;
};
self.getBottomPipe = function () {
return bottomPipe;
};
return self;
});
var Rocket = Container.expand(function () {
var self = Container.call(this);
var rocketGraphics = self.attachAsset('rocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = 0;
self.gravity = 0.5;
self.jumpForce = -10;
self.rotation = 0;
self.isDead = false;
self.jump = function () {
if (self.isDead) return;
self.velocity = self.jumpForce;
LK.getSound('jump').play();
};
self.update = function () {
if (self.isDead) return;
self.velocity += self.gravity;
self.y += self.velocity;
// Calculate rotation based on velocity (between -30 and 90 degrees)
var targetRotation = Math.max(-Math.PI / 6, Math.min(Math.PI / 2, self.velocity * 0.04));
self.rotation = targetRotation;
rocketGraphics.rotation = self.rotation;
// Check boundaries
if (self.y < 50) {
self.y = 50;
self.velocity = 0;
} else if (self.y > 2732 - 50) {
self.die();
}
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xff0000, 500);
// Save high score
addHighScore(LK.getScore());
// Trigger game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var gameStarted = false;
var rocket;
var pipes = [];
var coins = [];
var pipeSpawnTimer = 0;
var pipeSpawnInterval = 120; // Frames between pipe spawns
var minGapY = 400;
var maxGapY = 2732 - 400;
var lastIntersecting = false;
var lastCoinCollected = false;
var leaderboard;
var highScoreBtn;
var showingLeaderboard = false;
// Create UI elements
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Add high score button
highScoreBtn = new Text2('HIGH SCORES', {
size: 50,
fill: 0xFFFFFF
});
highScoreBtn.anchor.set(1, 0);
highScoreBtn.x = -50;
highScoreBtn.y = 50;
highScoreBtn.interactive = true;
highScoreBtn.down = function () {
if (!showingLeaderboard && !rocket.isDead) {
showLeaderboard();
}
};
LK.gui.topRight.addChild(highScoreBtn);
// Create leaderboard
leaderboard = new Leaderboard();
leaderboard.x = 2048 / 2;
leaderboard.y = 300;
leaderboard.visible = false;
game.addChild(leaderboard);
var instructionsTxt = new Text2('Tap to start\nThen tap to fly', {
size: 80,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionsTxt);
// Create background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
// Create rocket
function initGame() {
// Create rocket if it doesn't exist
if (!rocket) {
rocket = new Rocket();
rocket.x = 400;
rocket.y = 2732 / 2;
game.addChild(rocket);
} else {
rocket.y = 2732 / 2;
rocket.velocity = 0;
rocket.rotation = 0;
rocket.isDead = false;
}
// Clear existing pipes
for (var i = 0; i < pipes.length; i++) {
pipes[i].destroy();
}
pipes = [];
// Clear existing coins
for (var i = 0; i < coins.length; i++) {
coins[i].destroy();
}
coins = [];
// Reset variables
pipeSpawnTimer = 0;
LK.setScore(0);
scoreTxt.setText('0');
gameStarted = false;
instructionsTxt.visible = true;
lastIntersecting = false;
}
// Initialize the game
initGame();
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.6,
duration: 1000
}
});
// Handle tap to jump and start game
game.down = function (x, y, obj) {
if (showingLeaderboard) {
hideLeaderboard();
return;
}
if (!gameStarted) {
gameStarted = true;
instructionsTxt.visible = false;
}
if (rocket && !rocket.isDead) {
rocket.jump();
}
};
// Create a new pipe at the right edge of the screen
function spawnPipe() {
var pipe = new Pipe();
pipe.x = 2048 + 150; // Start just off the right side of the screen
// Randomize gap position
var gapY = minGapY + Math.random() * (maxGapY - minGapY);
pipe.setGapPosition(gapY);
game.addChild(pipe);
pipes.push(pipe);
// Add a coin in the middle of the gap (70% chance)
if (Math.random() < 0.7) {
var coin = new Coin();
coin.x = pipe.x;
coin.y = gapY; // Position coin in the middle of the gap
game.addChild(coin);
coins.push(coin);
}
}
// Check for collisions between rocket and pipes
function checkCollisions() {
if (!rocket || rocket.isDead || !gameStarted) return;
var collisionDetected = false;
var coinCollected = false;
// Create rocket collision rectangle once
var rocketBounds = new Rectangle(rocket.x - 40,
// Half width
rocket.y - 40,
// Half height
80,
// Width
80 // Height
);
// Check collisions with pipes
for (var i = 0; i < pipes.length; i++) {
var pipe = pipes[i];
var topPipe = pipe.getTopPipe();
var bottomPipe = pipe.getBottomPipe();
// Convert pipe coordinates to game coordinates for collision detection
var topGlobal = pipe.toGlobal(topPipe.position);
var bottomGlobal = pipe.toGlobal(bottomPipe.position);
var topGame = game.toLocal(topGlobal);
var bottomGame = game.toLocal(bottomGlobal);
// Create collision rectangles
var topPipeBounds = new Rectangle(topGame.x - 112.5,
// Half width (accounting for scale 1.5)
topGame.y - 800,
// Full height (anchored at bottom)
225,
// Width (accounting for scale 1.5)
800 // Height
);
var bottomPipeBounds = new Rectangle(bottomGame.x - 112.5,
// Half width (accounting for scale 1.5)
bottomGame.y,
// Anchored at top
225,
// Width (accounting for scale 1.5)
800 // Height
);
// Check for collisions
if (intersectRectangles(rocketBounds, topPipeBounds) || intersectRectangles(rocketBounds, bottomPipeBounds)) {
collisionDetected = true;
break;
}
// Check if rocket has passed this pipe pair
if (!pipe.scored && pipe.x < rocket.x - 100) {
pipe.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore().toString());
LK.getSound('score').play();
}
}
// Check for coin collisions
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && coin.visible) {
var coinBounds = new Rectangle(coin.x - 25,
// Half width
coin.y - 25,
// Half height
50,
// Width
50 // Height
);
if (intersectRectangles(rocketBounds, coinBounds)) {
coin.collect();
LK.setScore(LK.getScore() + 3); // Coins worth 3 points
scoreTxt.setText(LK.getScore().toString());
LK.getSound('coin').play();
coinCollected = true;
}
}
}
// Check for state transition (not colliding -> colliding)
if (!lastIntersecting && collisionDetected) {
rocket.die();
}
lastIntersecting = collisionDetected;
}
// Helper function to check if two rectangles intersect
function intersectRectangles(rect1, rect2) {
return !(rect1.x > rect2.x + rect2.width || rect1.x + rect1.width < rect2.x || rect1.y > rect2.y + rect2.height || rect1.y + rect1.height < rect2.y);
}
// Function to show leaderboard
function showLeaderboard() {
showingLeaderboard = true;
gameStarted = false;
leaderboard.updateScores(storage.highScores || []);
leaderboard.visible = true;
}
// Function to hide leaderboard
function hideLeaderboard() {
showingLeaderboard = false;
leaderboard.visible = false;
if (!rocket.isDead) {
gameStarted = true;
}
}
// Function to add a score to the leaderboard
function addHighScore(score) {
var highScores = storage.highScores || [];
highScores.push(score);
highScores.sort(function (a, b) {
return b - a;
}); // Sort in descending order
if (highScores.length > 10) {
highScores = highScores.slice(0, 10); // Keep only top 10
}
storage.highScores = highScores;
return highScores;
}
// Game update loop
game.update = function () {
// Don't update game when showing leaderboard
if (showingLeaderboard) {
return;
}
if (gameStarted) {
// Update rocket
if (rocket) {
rocket.update();
}
// Update pipes
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].update();
// Remove pipes that have moved off screen
if (pipes[i].x < -200) {
pipes[i].destroy();
pipes.splice(i, 1);
}
}
// Update coins
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].update();
// Remove coins that have moved off screen
if (coins[i].x < -100) {
coins[i].destroy();
coins.splice(i, 1);
}
}
// Spawn new pipes
pipeSpawnTimer++;
if (pipeSpawnTimer >= pipeSpawnInterval) {
spawnPipe();
pipeSpawnTimer = 0;
// Make the game slightly harder over time by decreasing the spawn interval
pipeSpawnInterval = Math.max(80, pipeSpawnInterval - 1);
}
// Check for collisions
checkCollisions();
// Adjust pipe speed based on score to increase difficulty
var baseSpeed = 5;
var speedIncrease = Math.min(5, Math.floor(LK.getScore() / 10));
for (var i = 0; i < pipes.length; i++) {
pipes[i].speed = baseSpeed + speedIncrease;
}
// Update coin speeds to match pipes
for (var i = 0; i < coins.length; i++) {
coins[i].speed = baseSpeed + speedIncrease;
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScores: []
});
/****
* Classes
****/
var Coin = Container.expand(function () {
var self = Container.call(this);
// Create coin visual
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.collected = false;
self.rotation = 0;
// Animate the coin
self.update = function () {
self.x -= self.speed;
self.rotation += 0.05;
coinGraphics.rotation = self.rotation;
};
// Flash and mark as collected
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.effects.flashObject(self, 0xffff00, 300);
// Fade out and shrink
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 300,
onFinish: function onFinish() {
self.visible = false;
}
});
}
};
return self;
});
var Leaderboard = Container.expand(function () {
var self = Container.call(this);
// Create title text
var titleText = new Text2('HIGH SCORES', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = 50;
self.addChild(titleText);
// Array to hold score text objects
self.scoreTexts = [];
// Method to update the displayed scores
self.updateScores = function (scores) {
// Remove existing score texts
for (var i = 0; i < self.scoreTexts.length; i++) {
self.scoreTexts[i].destroy();
}
self.scoreTexts = [];
// Create new score texts
var maxToShow = Math.min(5, scores.length);
for (var i = 0; i < maxToShow; i++) {
var scoreText = new Text2(i + 1 + ". " + scores[i], {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.y = 150 + i * 80;
self.addChild(scoreText);
self.scoreTexts.push(scoreText);
}
// If no scores yet, show a message
if (scores.length === 0) {
var noScoreText = new Text2("No scores yet!", {
size: 60,
fill: 0xFFFFFF
});
noScoreText.anchor.set(0.5, 0);
noScoreText.y = 150;
self.addChild(noScoreText);
self.scoreTexts.push(noScoreText);
}
};
// Create back button
var backText = new Text2("BACK TO GAME", {
size: 60,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0);
backText.y = 600;
backText.interactive = true;
// Handle back button click
backText.down = function () {
self.visible = false;
};
self.addChild(backText);
return self;
});
var Pipe = Container.expand(function () {
var self = Container.call(this);
// Each pipe consists of top and bottom segments
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 1.0,
scaleX: 1.5
});
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0.0,
scaleX: 1.5
});
self.speed = 5;
self.gapHeight = 450; // Increased gap height
self.scored = false;
self.setGapPosition = function (gapY) {
topPipe.y = gapY - self.gapHeight / 2;
bottomPipe.y = gapY + self.gapHeight / 2;
};
self.update = function () {
self.x -= self.speed;
};
self.getTopPipe = function () {
return topPipe;
};
self.getBottomPipe = function () {
return bottomPipe;
};
return self;
});
var Rocket = Container.expand(function () {
var self = Container.call(this);
var rocketGraphics = self.attachAsset('rocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = 0;
self.gravity = 0.5;
self.jumpForce = -10;
self.rotation = 0;
self.isDead = false;
self.jump = function () {
if (self.isDead) return;
self.velocity = self.jumpForce;
LK.getSound('jump').play();
};
self.update = function () {
if (self.isDead) return;
self.velocity += self.gravity;
self.y += self.velocity;
// Calculate rotation based on velocity (between -30 and 90 degrees)
var targetRotation = Math.max(-Math.PI / 6, Math.min(Math.PI / 2, self.velocity * 0.04));
self.rotation = targetRotation;
rocketGraphics.rotation = self.rotation;
// Check boundaries
if (self.y < 50) {
self.y = 50;
self.velocity = 0;
} else if (self.y > 2732 - 50) {
self.die();
}
};
self.die = function () {
if (self.isDead) return;
self.isDead = true;
LK.getSound('crash').play();
LK.effects.flashObject(self, 0xff0000, 500);
// Save high score
addHighScore(LK.getScore());
// Trigger game over after a short delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game variables
var gameStarted = false;
var rocket;
var pipes = [];
var coins = [];
var pipeSpawnTimer = 0;
var pipeSpawnInterval = 120; // Frames between pipe spawns
var minGapY = 400;
var maxGapY = 2732 - 400;
var lastIntersecting = false;
var lastCoinCollected = false;
var leaderboard;
var highScoreBtn;
var showingLeaderboard = false;
// Create UI elements
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Add high score button
highScoreBtn = new Text2('HIGH SCORES', {
size: 50,
fill: 0xFFFFFF
});
highScoreBtn.anchor.set(1, 0);
highScoreBtn.x = -50;
highScoreBtn.y = 50;
highScoreBtn.interactive = true;
highScoreBtn.down = function () {
if (!showingLeaderboard && !rocket.isDead) {
showLeaderboard();
}
};
LK.gui.topRight.addChild(highScoreBtn);
// Create leaderboard
leaderboard = new Leaderboard();
leaderboard.x = 2048 / 2;
leaderboard.y = 300;
leaderboard.visible = false;
game.addChild(leaderboard);
var instructionsTxt = new Text2('Tap to start\nThen tap to fly', {
size: 80,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionsTxt);
// Create background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
// Create rocket
function initGame() {
// Create rocket if it doesn't exist
if (!rocket) {
rocket = new Rocket();
rocket.x = 400;
rocket.y = 2732 / 2;
game.addChild(rocket);
} else {
rocket.y = 2732 / 2;
rocket.velocity = 0;
rocket.rotation = 0;
rocket.isDead = false;
}
// Clear existing pipes
for (var i = 0; i < pipes.length; i++) {
pipes[i].destroy();
}
pipes = [];
// Clear existing coins
for (var i = 0; i < coins.length; i++) {
coins[i].destroy();
}
coins = [];
// Reset variables
pipeSpawnTimer = 0;
LK.setScore(0);
scoreTxt.setText('0');
gameStarted = false;
instructionsTxt.visible = true;
lastIntersecting = false;
}
// Initialize the game
initGame();
// Play background music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.6,
duration: 1000
}
});
// Handle tap to jump and start game
game.down = function (x, y, obj) {
if (showingLeaderboard) {
hideLeaderboard();
return;
}
if (!gameStarted) {
gameStarted = true;
instructionsTxt.visible = false;
}
if (rocket && !rocket.isDead) {
rocket.jump();
}
};
// Create a new pipe at the right edge of the screen
function spawnPipe() {
var pipe = new Pipe();
pipe.x = 2048 + 150; // Start just off the right side of the screen
// Randomize gap position
var gapY = minGapY + Math.random() * (maxGapY - minGapY);
pipe.setGapPosition(gapY);
game.addChild(pipe);
pipes.push(pipe);
// Add a coin in the middle of the gap (70% chance)
if (Math.random() < 0.7) {
var coin = new Coin();
coin.x = pipe.x;
coin.y = gapY; // Position coin in the middle of the gap
game.addChild(coin);
coins.push(coin);
}
}
// Check for collisions between rocket and pipes
function checkCollisions() {
if (!rocket || rocket.isDead || !gameStarted) return;
var collisionDetected = false;
var coinCollected = false;
// Create rocket collision rectangle once
var rocketBounds = new Rectangle(rocket.x - 40,
// Half width
rocket.y - 40,
// Half height
80,
// Width
80 // Height
);
// Check collisions with pipes
for (var i = 0; i < pipes.length; i++) {
var pipe = pipes[i];
var topPipe = pipe.getTopPipe();
var bottomPipe = pipe.getBottomPipe();
// Convert pipe coordinates to game coordinates for collision detection
var topGlobal = pipe.toGlobal(topPipe.position);
var bottomGlobal = pipe.toGlobal(bottomPipe.position);
var topGame = game.toLocal(topGlobal);
var bottomGame = game.toLocal(bottomGlobal);
// Create collision rectangles
var topPipeBounds = new Rectangle(topGame.x - 112.5,
// Half width (accounting for scale 1.5)
topGame.y - 800,
// Full height (anchored at bottom)
225,
// Width (accounting for scale 1.5)
800 // Height
);
var bottomPipeBounds = new Rectangle(bottomGame.x - 112.5,
// Half width (accounting for scale 1.5)
bottomGame.y,
// Anchored at top
225,
// Width (accounting for scale 1.5)
800 // Height
);
// Check for collisions
if (intersectRectangles(rocketBounds, topPipeBounds) || intersectRectangles(rocketBounds, bottomPipeBounds)) {
collisionDetected = true;
break;
}
// Check if rocket has passed this pipe pair
if (!pipe.scored && pipe.x < rocket.x - 100) {
pipe.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore().toString());
LK.getSound('score').play();
}
}
// Check for coin collisions
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected && coin.visible) {
var coinBounds = new Rectangle(coin.x - 25,
// Half width
coin.y - 25,
// Half height
50,
// Width
50 // Height
);
if (intersectRectangles(rocketBounds, coinBounds)) {
coin.collect();
LK.setScore(LK.getScore() + 3); // Coins worth 3 points
scoreTxt.setText(LK.getScore().toString());
LK.getSound('coin').play();
coinCollected = true;
}
}
}
// Check for state transition (not colliding -> colliding)
if (!lastIntersecting && collisionDetected) {
rocket.die();
}
lastIntersecting = collisionDetected;
}
// Helper function to check if two rectangles intersect
function intersectRectangles(rect1, rect2) {
return !(rect1.x > rect2.x + rect2.width || rect1.x + rect1.width < rect2.x || rect1.y > rect2.y + rect2.height || rect1.y + rect1.height < rect2.y);
}
// Function to show leaderboard
function showLeaderboard() {
showingLeaderboard = true;
gameStarted = false;
leaderboard.updateScores(storage.highScores || []);
leaderboard.visible = true;
}
// Function to hide leaderboard
function hideLeaderboard() {
showingLeaderboard = false;
leaderboard.visible = false;
if (!rocket.isDead) {
gameStarted = true;
}
}
// Function to add a score to the leaderboard
function addHighScore(score) {
var highScores = storage.highScores || [];
highScores.push(score);
highScores.sort(function (a, b) {
return b - a;
}); // Sort in descending order
if (highScores.length > 10) {
highScores = highScores.slice(0, 10); // Keep only top 10
}
storage.highScores = highScores;
return highScores;
}
// Game update loop
game.update = function () {
// Don't update game when showing leaderboard
if (showingLeaderboard) {
return;
}
if (gameStarted) {
// Update rocket
if (rocket) {
rocket.update();
}
// Update pipes
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].update();
// Remove pipes that have moved off screen
if (pipes[i].x < -200) {
pipes[i].destroy();
pipes.splice(i, 1);
}
}
// Update coins
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].update();
// Remove coins that have moved off screen
if (coins[i].x < -100) {
coins[i].destroy();
coins.splice(i, 1);
}
}
// Spawn new pipes
pipeSpawnTimer++;
if (pipeSpawnTimer >= pipeSpawnInterval) {
spawnPipe();
pipeSpawnTimer = 0;
// Make the game slightly harder over time by decreasing the spawn interval
pipeSpawnInterval = Math.max(80, pipeSpawnInterval - 1);
}
// Check for collisions
checkCollisions();
// Adjust pipe speed based on score to increase difficulty
var baseSpeed = 5;
var speedIncrease = Math.min(5, Math.floor(LK.getScore() / 10));
for (var i = 0; i < pipes.length; i++) {
pipes[i].speed = baseSpeed + speedIncrease;
}
// Update coin speeds to match pipes
for (var i = 0; i < coins.length; i++) {
coins[i].speed = baseSpeed + speedIncrease;
}
}
};