/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Bird = Container.expand(function () { var self = Container.call(this); // Bird graphics var birdGraphics = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); // Add slow flapping animation tween(birdGraphics, { y: 10 }, { duration: 1000, easing: tween.easeInOutQuad, loop: true, yoyo: true }); // Bird physics properties self.velocity = 0; self.gravity = 0.6; // Decreased gravity for less realistic falling self.terminalVelocity = 12; // Decreased maximum falling speed self.flapStrength = -11; // Decreased from -14 to make bird jump less dramatic self.isDead = false; // Flap the bird self.flap = function () { if (!self.isDead) { self.velocity = self.flapStrength; // Add a small immediate position change for less natural, more game-like movement tween(self, { y: self.y - 20 }, { duration: 50, easing: tween.easeOutQuad }); LK.getSound('flap').play(); // Rotate bird up when flapping with more immediate rotation tween(self, { rotation: -0.4 }, { duration: 150, easing: tween.easeOutCubic // Faster rotation }); } }; self.die = function () { self.isDead = true; LK.getSound('hit').play(); LK.effects.flashObject(self, 0xFF0000, 500); LK.effects.flashScreen(0xFF0000, 800); // Flash entire screen red // Create text to inform player about the cycle var cycleText = new Text2('REPEAT THE CYCLE', { size: 120, fill: 0xFF0000 }); cycleText.anchor.set(0.5, 0.5); cycleText.x = 2048 / 2; cycleText.y = 2732 / 2 - 300; game.addChild(cycleText); }; self.update = function () { if (self.isDead) { return; } // Apply gravity with acceleration curve self.velocity += self.gravity; // Apply terminal velocity - prevents bird from falling too fast if (self.velocity > self.terminalVelocity) { self.velocity = self.terminalVelocity; } else if (self.velocity > 8) { // When bird reaches certain speed, start to slow it down self.velocity -= 0.1; // Gradually reduce velocity } self.y += self.velocity; // Simpler rotation based on velocity with less dampening for arcade-style movement var targetRotation = Math.min(0.8, Math.max(-0.4, self.velocity * 0.04)); tween(self, { rotation: targetRotation }, { duration: 100, // Faster rotation transition easing: tween.easeOutQuad }); // Check boundaries if (self.y < 0) { self.y = 0; self.velocity = 0; } if (self.y > 2732) { self.die(); // Add delay before game over to show the message LK.setTimeout(function () { LK.showGameOver(); }, 1500); } }; return self; }); var Pipe = Container.expand(function () { var self = Container.call(this); // Pipe properties self.speed = baseSpeed; self.scored = false; // Create top pipe (now much taller to extend to top of screen) var topPipe = self.attachAsset('pipe', { anchorX: 0.5, anchorY: 1.0, height: 2000 // Much taller to ensure it reaches top of screen }); // Create top pipe cap var topPipeCap = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 1.0, y: -500 }); // Create bottom pipe (now much taller to extend to bottom of screen) var bottomPipe = self.attachAsset('pipe', { anchorX: 0.5, anchorY: 0.0, height: 2000, // Much taller to ensure it reaches bottom of screen y: 200 // Gap will be between top and bottom pipes }); // Create bottom pipe cap var bottomPipeCap = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 0.0, y: 200 }); // Set pipe gap self.setGap = function (gapPosition, gapSize) { topPipe.y = gapPosition - gapSize / 2; topPipeCap.y = topPipe.y; bottomPipe.y = gapPosition + gapSize / 2; bottomPipeCap.y = bottomPipe.y; }; self.update = function () { // Move pipe left self.x -= self.speed; // Check if pipe is offscreen (adjusted for wider pipes) if (self.x < -250) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game state variables var bird; var pipes = []; var isGameStarted = false; var spawnInterval; var score = 0; var highScore = storage.highScore || 0; var difficulty = 1; var baseSpeed = 8; // Increased from 5 to make the game faster var baseInterval = 2300; // Decreased from 2500 to create slightly closer pipes var gameTimeElapsed = 0; // Track time elapsed in milliseconds var timerInterval; // Interval for tracking game time var deathTimeLimit = 320000; // 5 minutes and 20 seconds in milliseconds // Background var background = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5 }); background.x = 2048 / 2; background.y = 2732 / 2; background.scale.set(1.5); // Scale up background for zoomed effect game.addChild(background); // Score text var scoreTxt = new Text2('0', { size: 150, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 50; // High score text var highScoreTxt = new Text2('Best: 0', { size: 80, fill: 0xFFFFFF }); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.setText('Best: ' + highScore); LK.gui.top.addChild(highScoreTxt); highScoreTxt.y = 220; // Timer text to show countdown var timerTxt = new Text2('5:20', { size: 80, fill: 0xFFFFFF }); // Ensure style object exists timerTxt.style = timerTxt.style || {}; timerTxt.anchor.set(0.5, 0); LK.gui.top.addChild(timerTxt); timerTxt.y = 310; // Initialize bird function initBird() { bird = new Bird(); bird.x = 500; // Position bird more to the left for better zoomed view bird.y = 2732 / 2; // Scale bird up for zoomed in effect bird.scale.set(1.5); game.addChild(bird); } // Create a new pipe function spawnPipe() { if (!isGameStarted) { return; } var pipe = new Pipe(); // Position pipes further right for zoomed view pipe.x = 2048 + 150; // Set pipe speed based on current difficulty pipe.speed = baseSpeed * difficulty; // Move gap position higher (40% of screen height instead of 50%) var gapPosition = 2732 * 0.4 + (Math.random() * 200 - 100); // Higher placement ± 100px random variation // Fixed gap size that's comfortable to navigate through var gapSize = 550; // Slightly larger gap for zoomed view pipe.setGap(gapPosition, gapSize); // Scale pipes up for zoomed in effect pipe.scale.set(1.5); pipes.push(pipe); game.addChild(pipe); } // Start game function startGame() { if (isGameStarted) { return; } isGameStarted = true; score = 0; difficulty = 1; gameTimeElapsed = 0; // Reset game time elapsed scoreTxt.setText(score); // Clear any existing pipes for (var i = pipes.length - 1; i >= 0; i--) { pipes[i].destroy(); } pipes = []; // Reset bird position if (bird) { bird.destroy(); } initBird(); // Start spawning pipes with fixed interval spawnInterval = LK.setInterval(spawnPipe, baseInterval); // Start timer to track game time if (timerInterval) { LK.clearInterval(timerInterval); } timerInterval = LK.setInterval(function () { gameTimeElapsed += 100; // Increment by 100ms each tick }, 100); // Stop any existing music before playing new music LK.stopMusic(); // Play background music only once LK.playMusic('bgMusic', { loop: false }); // Listen for game pause/resume events to control audio LK.on('pause', function () { // Pause music when game is paused LK.stopMusic(); }); LK.on('resume', function () { // Resume music when game is resumed LK.playMusic('bgMusic'); }); } //}1m} // Initialize game initBird(); highScoreTxt.setText('Best: ' + highScore); // Game input game.down = function (x, y, obj) { if (!isGameStarted) { startGame(); } if (bird && !bird.isDead) { bird.flap(); } }; // Main game update game.update = function () { if (!isGameStarted) { return; } // Update timer display if (gameTimeElapsed < deathTimeLimit) { var timeLeft = deathTimeLimit - gameTimeElapsed; var minutes = Math.floor(timeLeft / 60000); var seconds = Math.floor(timeLeft % 60000 / 1000); timerTxt.setText(minutes + ':' + (seconds < 10 ? '0' + seconds : seconds)); // Change color when time is running out (last 30 seconds) if (timeLeft <= 30000) { timerTxt.style.fill = 0xFF0000; // Make text blink when time is really low (last 10 seconds) if (timeLeft <= 10000) { timerTxt.alpha = Math.sin(gameTimeElapsed / 200) * 0.5 + 0.5; } } } // Check if time limit has been reached (5 minutes and 5 seconds) if (gameTimeElapsed >= deathTimeLimit && bird && !bird.isDead) { // Brutally kill the bird after time limit LK.clearInterval(timerInterval); // Stop the timer timerTxt.setText('0:00'); timerTxt.style.fill = 0xFF0000; timerTxt.alpha = 1; // Create brutal death effect LK.effects.flashScreen(0xFF0000, 800); // Flash screen red LK.getSound('hit').play(); // Play hit sound // Make bird explode with dramatic scale and color changes tween(bird, { rotation: Math.PI * 4, // Spin multiple times scaleX: 3, scaleY: 3, alpha: 0 // Fade out bird }, { duration: 1000, easing: tween.easeInBack, onFinish: function onFinish() { // Show game over after animation finishes LK.showGameOver(); } }); // Set bird as dead to prevent further updates bird.isDead = true; // Create text to inform player var deathText = new Text2('REPEAT THE CYCLE', { size: 120, fill: 0xFF0000 }); deathText.anchor.set(0.5, 0.5); deathText.x = 2048 / 2; deathText.y = 2732 / 2 - 300; game.addChild(deathText); return; // Skip the rest of the update } // Update all pipes for (var i = pipes.length - 1; i >= 0; i--) { var pipe = pipes[i]; // Check for scoring (when bird passes pipe) if (!pipe.scored && bird && bird.x > pipe.x) { pipe.scored = true; score += 1; scoreTxt.setText(score); LK.setScore(score); LK.getSound('score').play(); // Increase difficulty every 5 points if (score % 5 === 0) { difficulty += 0.2; // Update all existing pipes to the new speed for (var k = 0; k < pipes.length; k++) { pipes[k].speed = baseSpeed * difficulty; } // Clear and reset spawn interval with fixed timing LK.clearInterval(spawnInterval); spawnInterval = LK.setInterval(spawnPipe, baseInterval); } // Update high score if needed if (score > highScore) { highScore = score; storage.highScore = highScore; highScoreTxt.setText('Best: ' + highScore); } } // Check for collision with bird if (bird && !bird.isDead) { // Get pipe children for collision checks var pipeChildren = pipe.children; for (var j = 0; j < pipeChildren.length; j++) { if (bird.intersects(pipeChildren[j])) { bird.die(); // Add delay before game over to show the message LK.setTimeout(function () { LK.showGameOver(); }, 1500); break; } } } // Remove pipe if it's off screen if (pipe.x < -200) { pipe.destroy(); pipes.splice(i, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
// Bird graphics
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
// Add slow flapping animation
tween(birdGraphics, {
y: 10
}, {
duration: 1000,
easing: tween.easeInOutQuad,
loop: true,
yoyo: true
});
// Bird physics properties
self.velocity = 0;
self.gravity = 0.6; // Decreased gravity for less realistic falling
self.terminalVelocity = 12; // Decreased maximum falling speed
self.flapStrength = -11; // Decreased from -14 to make bird jump less dramatic
self.isDead = false;
// Flap the bird
self.flap = function () {
if (!self.isDead) {
self.velocity = self.flapStrength;
// Add a small immediate position change for less natural, more game-like movement
tween(self, {
y: self.y - 20
}, {
duration: 50,
easing: tween.easeOutQuad
});
LK.getSound('flap').play();
// Rotate bird up when flapping with more immediate rotation
tween(self, {
rotation: -0.4
}, {
duration: 150,
easing: tween.easeOutCubic // Faster rotation
});
}
};
self.die = function () {
self.isDead = true;
LK.getSound('hit').play();
LK.effects.flashObject(self, 0xFF0000, 500);
LK.effects.flashScreen(0xFF0000, 800); // Flash entire screen red
// Create text to inform player about the cycle
var cycleText = new Text2('REPEAT THE CYCLE', {
size: 120,
fill: 0xFF0000
});
cycleText.anchor.set(0.5, 0.5);
cycleText.x = 2048 / 2;
cycleText.y = 2732 / 2 - 300;
game.addChild(cycleText);
};
self.update = function () {
if (self.isDead) {
return;
}
// Apply gravity with acceleration curve
self.velocity += self.gravity;
// Apply terminal velocity - prevents bird from falling too fast
if (self.velocity > self.terminalVelocity) {
self.velocity = self.terminalVelocity;
} else if (self.velocity > 8) {
// When bird reaches certain speed, start to slow it down
self.velocity -= 0.1; // Gradually reduce velocity
}
self.y += self.velocity;
// Simpler rotation based on velocity with less dampening for arcade-style movement
var targetRotation = Math.min(0.8, Math.max(-0.4, self.velocity * 0.04));
tween(self, {
rotation: targetRotation
}, {
duration: 100,
// Faster rotation transition
easing: tween.easeOutQuad
});
// Check boundaries
if (self.y < 0) {
self.y = 0;
self.velocity = 0;
}
if (self.y > 2732) {
self.die();
// Add delay before game over to show the message
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
};
return self;
});
var Pipe = Container.expand(function () {
var self = Container.call(this);
// Pipe properties
self.speed = baseSpeed;
self.scored = false;
// Create top pipe (now much taller to extend to top of screen)
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 1.0,
height: 2000 // Much taller to ensure it reaches top of screen
});
// Create top pipe cap
var topPipeCap = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 1.0,
y: -500
});
// Create bottom pipe (now much taller to extend to bottom of screen)
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0.0,
height: 2000,
// Much taller to ensure it reaches bottom of screen
y: 200 // Gap will be between top and bottom pipes
});
// Create bottom pipe cap
var bottomPipeCap = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 0.0,
y: 200
});
// Set pipe gap
self.setGap = function (gapPosition, gapSize) {
topPipe.y = gapPosition - gapSize / 2;
topPipeCap.y = topPipe.y;
bottomPipe.y = gapPosition + gapSize / 2;
bottomPipeCap.y = bottomPipe.y;
};
self.update = function () {
// Move pipe left
self.x -= self.speed;
// Check if pipe is offscreen (adjusted for wider pipes)
if (self.x < -250) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var bird;
var pipes = [];
var isGameStarted = false;
var spawnInterval;
var score = 0;
var highScore = storage.highScore || 0;
var difficulty = 1;
var baseSpeed = 8; // Increased from 5 to make the game faster
var baseInterval = 2300; // Decreased from 2500 to create slightly closer pipes
var gameTimeElapsed = 0; // Track time elapsed in milliseconds
var timerInterval; // Interval for tracking game time
var deathTimeLimit = 320000; // 5 minutes and 20 seconds in milliseconds
// Background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
background.scale.set(1.5); // Scale up background for zoomed effect
game.addChild(background);
// Score text
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
// High score text
var highScoreTxt = new Text2('Best: 0', {
size: 80,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(0.5, 0);
highScoreTxt.setText('Best: ' + highScore);
LK.gui.top.addChild(highScoreTxt);
highScoreTxt.y = 220;
// Timer text to show countdown
var timerTxt = new Text2('5:20', {
size: 80,
fill: 0xFFFFFF
});
// Ensure style object exists
timerTxt.style = timerTxt.style || {};
timerTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(timerTxt);
timerTxt.y = 310;
// Initialize bird
function initBird() {
bird = new Bird();
bird.x = 500; // Position bird more to the left for better zoomed view
bird.y = 2732 / 2;
// Scale bird up for zoomed in effect
bird.scale.set(1.5);
game.addChild(bird);
}
// Create a new pipe
function spawnPipe() {
if (!isGameStarted) {
return;
}
var pipe = new Pipe();
// Position pipes further right for zoomed view
pipe.x = 2048 + 150;
// Set pipe speed based on current difficulty
pipe.speed = baseSpeed * difficulty;
// Move gap position higher (40% of screen height instead of 50%)
var gapPosition = 2732 * 0.4 + (Math.random() * 200 - 100); // Higher placement ± 100px random variation
// Fixed gap size that's comfortable to navigate through
var gapSize = 550; // Slightly larger gap for zoomed view
pipe.setGap(gapPosition, gapSize);
// Scale pipes up for zoomed in effect
pipe.scale.set(1.5);
pipes.push(pipe);
game.addChild(pipe);
}
// Start game
function startGame() {
if (isGameStarted) {
return;
}
isGameStarted = true;
score = 0;
difficulty = 1;
gameTimeElapsed = 0; // Reset game time elapsed
scoreTxt.setText(score);
// Clear any existing pipes
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].destroy();
}
pipes = [];
// Reset bird position
if (bird) {
bird.destroy();
}
initBird();
// Start spawning pipes with fixed interval
spawnInterval = LK.setInterval(spawnPipe, baseInterval);
// Start timer to track game time
if (timerInterval) {
LK.clearInterval(timerInterval);
}
timerInterval = LK.setInterval(function () {
gameTimeElapsed += 100; // Increment by 100ms each tick
}, 100);
// Stop any existing music before playing new music
LK.stopMusic();
// Play background music only once
LK.playMusic('bgMusic', {
loop: false
});
// Listen for game pause/resume events to control audio
LK.on('pause', function () {
// Pause music when game is paused
LK.stopMusic();
});
LK.on('resume', function () {
// Resume music when game is resumed
LK.playMusic('bgMusic');
});
} //}1m}
// Initialize game
initBird();
highScoreTxt.setText('Best: ' + highScore);
// Game input
game.down = function (x, y, obj) {
if (!isGameStarted) {
startGame();
}
if (bird && !bird.isDead) {
bird.flap();
}
};
// Main game update
game.update = function () {
if (!isGameStarted) {
return;
}
// Update timer display
if (gameTimeElapsed < deathTimeLimit) {
var timeLeft = deathTimeLimit - gameTimeElapsed;
var minutes = Math.floor(timeLeft / 60000);
var seconds = Math.floor(timeLeft % 60000 / 1000);
timerTxt.setText(minutes + ':' + (seconds < 10 ? '0' + seconds : seconds));
// Change color when time is running out (last 30 seconds)
if (timeLeft <= 30000) {
timerTxt.style.fill = 0xFF0000;
// Make text blink when time is really low (last 10 seconds)
if (timeLeft <= 10000) {
timerTxt.alpha = Math.sin(gameTimeElapsed / 200) * 0.5 + 0.5;
}
}
}
// Check if time limit has been reached (5 minutes and 5 seconds)
if (gameTimeElapsed >= deathTimeLimit && bird && !bird.isDead) {
// Brutally kill the bird after time limit
LK.clearInterval(timerInterval); // Stop the timer
timerTxt.setText('0:00');
timerTxt.style.fill = 0xFF0000;
timerTxt.alpha = 1;
// Create brutal death effect
LK.effects.flashScreen(0xFF0000, 800); // Flash screen red
LK.getSound('hit').play(); // Play hit sound
// Make bird explode with dramatic scale and color changes
tween(bird, {
rotation: Math.PI * 4,
// Spin multiple times
scaleX: 3,
scaleY: 3,
alpha: 0 // Fade out bird
}, {
duration: 1000,
easing: tween.easeInBack,
onFinish: function onFinish() {
// Show game over after animation finishes
LK.showGameOver();
}
});
// Set bird as dead to prevent further updates
bird.isDead = true;
// Create text to inform player
var deathText = new Text2('REPEAT THE CYCLE', {
size: 120,
fill: 0xFF0000
});
deathText.anchor.set(0.5, 0.5);
deathText.x = 2048 / 2;
deathText.y = 2732 / 2 - 300;
game.addChild(deathText);
return; // Skip the rest of the update
}
// Update all pipes
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
// Check for scoring (when bird passes pipe)
if (!pipe.scored && bird && bird.x > pipe.x) {
pipe.scored = true;
score += 1;
scoreTxt.setText(score);
LK.setScore(score);
LK.getSound('score').play();
// Increase difficulty every 5 points
if (score % 5 === 0) {
difficulty += 0.2;
// Update all existing pipes to the new speed
for (var k = 0; k < pipes.length; k++) {
pipes[k].speed = baseSpeed * difficulty;
}
// Clear and reset spawn interval with fixed timing
LK.clearInterval(spawnInterval);
spawnInterval = LK.setInterval(spawnPipe, baseInterval);
}
// Update high score if needed
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
highScoreTxt.setText('Best: ' + highScore);
}
}
// Check for collision with bird
if (bird && !bird.isDead) {
// Get pipe children for collision checks
var pipeChildren = pipe.children;
for (var j = 0; j < pipeChildren.length; j++) {
if (bird.intersects(pipeChildren[j])) {
bird.die();
// Add delay before game over to show the message
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
break;
}
}
}
// Remove pipe if it's off screen
if (pipe.x < -200) {
pipe.destroy();
pipes.splice(i, 1);
}
}
};