User prompt
make the pipes extend to the top and bottom of the screen
User prompt
make the pipes bigger and more centered
Code edit (1 edits merged)
Please save this source code
User prompt
Flappy Flight
Initial prompt
To create the Flappy Bird game, first set up the game screen as portrait mode with a static background that scrolls endlessly to the left. The screen should not resize, and the game world moves forward from right to left. The player controls a bird that moves automatically to the right at a constant speed. The bird is affected by gravity, so it will constantly fall unless the player taps the screen. When the screen is tapped, the bird jumps slightly upwards, and the jump should have an animation to show the bird flapping its wings. If the player does not tap, the bird will fall, and the faster it falls, the more gravity pulls it downward. Create pipes that appear from the right side of the screen and move left. These pipes should always come in pairs: one top pipe and one bottom pipe. The space between these pipes (the gap) is where the player must fly through. The gap's vertical position is randomly chosen each time the pipes spawn. The pipes move left at a constant speed, and if the bird collides with any part of a pipe or the top/bottom of the screen, the game ends. The player’s goal is to fly through as many pairs of pipes as possible without hitting them. Each time the bird successfully flies through a gap between pipes, the score increases by 1, and the score is displayed at the top of the screen. Additionally, the game tracks a high score that is saved. When the bird crashes into a pipe or hits the ground or ceiling, the game ends. A "Game Over" screen appears, showing the player’s current score and high score, and the player must tap the screen again to restart the game. When restarted, the game resets: the bird is placed back in the starting position, the score resets to 0, the pipes reset, and the entire game loop begins again. You may also add extra polish, like showing a "Tap to Start" text before the game begins and playing sound effects for the bird’s flap, scoring points, and crashing into things.
/**** * 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);
}
}
};