/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Background = Container.expand(function () {
var self = Container.call(this);
self.backgroundLayers = [];
self.currentTheme = 0;
self.themes = ['background1', 'background2', 'background3'];
self.transitionTimer = 0;
self.transitionDuration = 1800; // 30 seconds at 60fps
self.decorativeElements = [];
// Create initial background
var bg1 = self.attachAsset(self.themes[self.currentTheme], {
anchorX: 0,
anchorY: 0
});
self.backgroundLayers.push(bg1);
// Add decorative elements based on theme
self.addDecorations = function (theme) {
// Clear existing decorations
for (var i = 0; i < self.decorativeElements.length; i++) {
self.decorativeElements[i].destroy();
}
self.decorativeElements = [];
if (theme === 0) {
// Day theme - add sun
var sun = self.addChild(new Sun());
sun.x = 1600;
sun.y = 300;
self.decorativeElements.push(sun);
} else if (theme === 2) {
// Night theme - add stars
for (var j = 0; j < 8; j++) {
var star = self.addChild(new Star());
star.x = Math.random() * 1800 + 100;
star.y = Math.random() * 600 + 100;
self.decorativeElements.push(star);
}
}
};
// Add initial decorations
self.addDecorations(self.currentTheme);
self.update = function () {
self.transitionTimer++;
// Update decorative elements
for (var k = 0; k < self.decorativeElements.length; k++) {
if (self.decorativeElements[k].update) {
self.decorativeElements[k].update();
}
}
if (self.transitionTimer >= self.transitionDuration) {
self.transitionTimer = 0;
self.currentTheme = (self.currentTheme + 1) % self.themes.length;
// Create new background for transition
var newBg = LK.getAsset(self.themes[self.currentTheme], {
anchorX: 0,
anchorY: 0,
alpha: 0
});
self.addChild(newBg);
self.backgroundLayers.push(newBg);
// Add new decorations for the new theme
self.addDecorations(self.currentTheme);
// Fade in new background
tween(newBg, {
alpha: 1
}, {
duration: 2000
});
// Fade out old backgrounds
for (var i = 0; i < self.backgroundLayers.length - 1; i++) {
var oldBg = self.backgroundLayers[i];
tween(oldBg, {
alpha: 0
}, {
duration: 2000,
onFinish: function onFinish() {
oldBg.destroy();
}
});
}
// Keep only the new background in array
self.backgroundLayers = [newBg];
}
};
return self;
});
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
// Add subtle shadow effect by scaling slightly
birdGraphics.scaleX = 1.2;
birdGraphics.scaleY = 1.2;
self.velocityY = 0;
self.gravity = 0.8;
self.flapPower = -15;
self.maxFallSpeed = 15;
self.isDead = false;
self.flap = function () {
if (!self.isDead) {
self.velocityY = self.flapPower;
LK.getSound('flap').play();
// Wing flap animation
tween(birdGraphics, {
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(birdGraphics, {
scaleY: 1.0
}, {
duration: 100
});
}
});
}
};
self.update = function () {
if (!self.isDead) {
// Apply gravity
self.velocityY += self.gravity;
// Limit fall speed
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
// Update position
self.y += self.velocityY;
// Rotate bird based on velocity
var targetRotation = Math.min(Math.max(self.velocityY * 0.1, -0.5), 1.5);
birdGraphics.rotation = targetRotation;
// Allow bird to pass through top of screen
if (self.y < -30) {
self.y = 2732 + 30; // Wrap to bottom of screen
}
// Check collision with ground
if (self.y > 2732 - 150 - 30) {
self.y = 2732 - 150 - 30;
self.die();
}
}
};
self.die = function () {
if (!self.isDead) {
self.isDead = true;
LK.getSound('hit').play();
// Death animation
tween(birdGraphics, {
rotation: Math.PI,
alpha: 0.7
}, {
duration: 1000
});
tween(self, {
y: 2732 - 150 - 30
}, {
duration: 1000,
easing: tween.bounceOut
});
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Add gentle floating animation
self.floatTimer = Math.random() * Math.PI * 2;
cloudGraphics.scaleX = 0.8 + Math.random() * 0.4;
cloudGraphics.scaleY = 0.8 + Math.random() * 0.4;
self.speed = -1;
self.update = function () {
self.x += self.speed;
self.floatTimer += 0.02;
cloudGraphics.y = Math.sin(self.floatTimer) * 3;
};
return self;
});
var Pipe = Container.expand(function () {
var self = Container.call(this);
self.gapSize = 480;
self.speed = -4;
self.scored = false;
// Top pipe - extends from top of screen to gap
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0
});
// Bottom pipe - extends from gap to bottom of screen
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0
});
// Create hitbox containers that will match the visible pipe areas
self.topHitbox = self.addChild(LK.getAsset('pipe', {
anchorX: 0.5,
anchorY: 0,
alpha: 0 // Invisible hitbox
}));
self.bottomHitbox = self.addChild(LK.getAsset('pipe', {
anchorX: 0.5,
anchorY: 0,
alpha: 0 // Invisible hitbox
}));
self.setGapPosition = function (gapY) {
// Position top pipe to end at gap start
topPipe.y = 0;
topPipe.scaleY = (gapY - self.gapSize / 2) / topPipe.height;
// Position bottom pipe to start at gap end
bottomPipe.y = gapY + self.gapSize / 2;
bottomPipe.scaleY = (2732 - 150 - (gapY + self.gapSize / 2)) / bottomPipe.height;
// Update hitboxes to match visible pipe areas
self.topHitbox.y = 0;
self.topHitbox.scaleY = (gapY - self.gapSize / 2) / self.topHitbox.height;
self.topHitbox.scaleX = topPipe.scaleX;
self.bottomHitbox.y = gapY + self.gapSize / 2;
self.bottomHitbox.scaleY = (2732 - 150 - (gapY + self.gapSize / 2)) / self.bottomHitbox.height;
self.bottomHitbox.scaleX = bottomPipe.scaleX;
};
// Custom intersects method that checks both hitboxes
self.intersects = function (other) {
return self.topHitbox.intersects(other) || self.bottomHitbox.intersects(other);
};
self.update = function () {
self.x += self.speed;
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
// Twinkling effect
self.twinkleTimer = Math.random() * Math.PI * 2;
self.update = function () {
self.twinkleTimer += 0.1;
starGraphics.alpha = 0.5 + Math.sin(self.twinkleTimer) * 0.5;
};
return self;
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var sunGraphics = self.attachAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
});
// Gentle pulsing animation
self.pulseTimer = 0;
self.update = function () {
self.pulseTimer += 0.05;
sunGraphics.scaleX = 1 + Math.sin(self.pulseTimer) * 0.1;
sunGraphics.scaleY = 1 + Math.sin(self.pulseTimer) * 0.1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
// Sky backgrounds with gradient-like colors
// Deep sky blue
// Sunset pink
// Night dark blue
// Bird with better proportions and color
// Bright orange bird
// Fluffy white clouds
// Soft white clouds
// Textured ground
// Grass green ground
// Pipes with better color scheme
// Teal pipe color
// Additional decorative elements
// Yellow sun
// Small stars for night
var bird;
var pipes = [];
var clouds = [];
var ground;
var backgroundSystem;
var gameStarted = false;
var gameWaitingToStart = true;
var pipeSpawnTimer = 0;
var cloudSpawnTimer = 0;
var difficultyTimer = 0;
// UI
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 100;
var instructionTxt = new Text2('TAP TO FLAP', {
size: 80,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionTxt);
// Initialize background system
backgroundSystem = game.addChild(new Background());
// Create ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - 150
}));
// Create bird
bird = game.addChild(new Bird());
bird.x = 300;
bird.y = 1366;
bird.isDead = true; // Start in idle state until game begins
// Initial clouds
for (var i = 0; i < 3; i++) {
var cloud = game.addChild(new Cloud());
cloud.x = Math.random() * 2048;
cloud.y = Math.random() * 800 + 200;
cloud.alpha = 0.7;
clouds.push(cloud);
}
function startGame() {
if (!gameStarted && gameWaitingToStart) {
gameStarted = true;
gameWaitingToStart = false;
instructionTxt.visible = false;
pipeSpawnTimer = 0; // Reset timer so first pipe appears at correct timing
LK.playMusic('background_music');
}
}
function spawnPipe() {
var pipe = game.addChild(new Pipe());
pipe.x = 2048 + 60;
// Dynamic difficulty - reduce gap size over time
var difficultyFactor = Math.min(LK.getScore() * 0.02, 0.3);
pipe.gapSize = Math.max(430 - difficultyFactor * 100, 360);
// Randomize gap position with more variation - ensure gap stays within playable area
var minGapY = pipe.gapSize / 2 + 200; // Minimum distance from top
var maxGapY = 2732 - 150 - pipe.gapSize / 2 - 200; // Maximum distance from ground
var gapY = Math.random() * (maxGapY - minGapY) + minGapY;
pipe.setGapPosition(gapY);
pipes.push(pipe);
}
function spawnCloud() {
var cloud = game.addChild(new Cloud());
cloud.x = 2048 + 100;
cloud.y = Math.random() * 1000 + 200;
cloud.alpha = 0.6;
cloud.scaleX = Math.random() * 0.5 + 0.5;
cloud.scaleY = Math.random() * 0.5 + 0.5;
clouds.push(cloud);
}
// Game input
game.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
bird.isDead = false; // Activate bird when game starts
}
if (gameStarted) {
bird.flap();
}
};
// Game update loop
game.update = function () {
// Update background system
backgroundSystem.update();
if (gameStarted && !bird.isDead && !gameWaitingToStart) {
// Spawn pipes
pipeSpawnTimer++;
if (pipeSpawnTimer >= 210) {
// Every 3.5 seconds
pipeSpawnTimer = 0;
spawnPipe();
}
// Spawn clouds
cloudSpawnTimer++;
if (cloudSpawnTimer >= 240) {
// Every 4 seconds
cloudSpawnTimer = 0;
spawnCloud();
}
// Update and check pipes
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
// Check for scoring
if (!pipe.scored && pipe.x + 60 < bird.x) {
pipe.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
}
// Check collision with bird
if (pipe.intersects(bird)) {
bird.die();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver(); // Immediate game over when touching pipe
}
// Remove off-screen pipes
if (pipe.x < -150) {
pipe.destroy();
pipes.splice(i, 1);
}
}
// Update and manage clouds
for (var j = clouds.length - 1; j >= 0; j--) {
var cloud = clouds[j];
if (cloud.x < -250) {
cloud.destroy();
clouds.splice(j, 1);
}
}
}
// Show game over immediately when bird dies from hitting ground
if (bird.isDead && bird.y >= 2732 - 150 - 30) {
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Background = Container.expand(function () {
var self = Container.call(this);
self.backgroundLayers = [];
self.currentTheme = 0;
self.themes = ['background1', 'background2', 'background3'];
self.transitionTimer = 0;
self.transitionDuration = 1800; // 30 seconds at 60fps
self.decorativeElements = [];
// Create initial background
var bg1 = self.attachAsset(self.themes[self.currentTheme], {
anchorX: 0,
anchorY: 0
});
self.backgroundLayers.push(bg1);
// Add decorative elements based on theme
self.addDecorations = function (theme) {
// Clear existing decorations
for (var i = 0; i < self.decorativeElements.length; i++) {
self.decorativeElements[i].destroy();
}
self.decorativeElements = [];
if (theme === 0) {
// Day theme - add sun
var sun = self.addChild(new Sun());
sun.x = 1600;
sun.y = 300;
self.decorativeElements.push(sun);
} else if (theme === 2) {
// Night theme - add stars
for (var j = 0; j < 8; j++) {
var star = self.addChild(new Star());
star.x = Math.random() * 1800 + 100;
star.y = Math.random() * 600 + 100;
self.decorativeElements.push(star);
}
}
};
// Add initial decorations
self.addDecorations(self.currentTheme);
self.update = function () {
self.transitionTimer++;
// Update decorative elements
for (var k = 0; k < self.decorativeElements.length; k++) {
if (self.decorativeElements[k].update) {
self.decorativeElements[k].update();
}
}
if (self.transitionTimer >= self.transitionDuration) {
self.transitionTimer = 0;
self.currentTheme = (self.currentTheme + 1) % self.themes.length;
// Create new background for transition
var newBg = LK.getAsset(self.themes[self.currentTheme], {
anchorX: 0,
anchorY: 0,
alpha: 0
});
self.addChild(newBg);
self.backgroundLayers.push(newBg);
// Add new decorations for the new theme
self.addDecorations(self.currentTheme);
// Fade in new background
tween(newBg, {
alpha: 1
}, {
duration: 2000
});
// Fade out old backgrounds
for (var i = 0; i < self.backgroundLayers.length - 1; i++) {
var oldBg = self.backgroundLayers[i];
tween(oldBg, {
alpha: 0
}, {
duration: 2000,
onFinish: function onFinish() {
oldBg.destroy();
}
});
}
// Keep only the new background in array
self.backgroundLayers = [newBg];
}
};
return self;
});
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
// Add subtle shadow effect by scaling slightly
birdGraphics.scaleX = 1.2;
birdGraphics.scaleY = 1.2;
self.velocityY = 0;
self.gravity = 0.8;
self.flapPower = -15;
self.maxFallSpeed = 15;
self.isDead = false;
self.flap = function () {
if (!self.isDead) {
self.velocityY = self.flapPower;
LK.getSound('flap').play();
// Wing flap animation
tween(birdGraphics, {
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(birdGraphics, {
scaleY: 1.0
}, {
duration: 100
});
}
});
}
};
self.update = function () {
if (!self.isDead) {
// Apply gravity
self.velocityY += self.gravity;
// Limit fall speed
if (self.velocityY > self.maxFallSpeed) {
self.velocityY = self.maxFallSpeed;
}
// Update position
self.y += self.velocityY;
// Rotate bird based on velocity
var targetRotation = Math.min(Math.max(self.velocityY * 0.1, -0.5), 1.5);
birdGraphics.rotation = targetRotation;
// Allow bird to pass through top of screen
if (self.y < -30) {
self.y = 2732 + 30; // Wrap to bottom of screen
}
// Check collision with ground
if (self.y > 2732 - 150 - 30) {
self.y = 2732 - 150 - 30;
self.die();
}
}
};
self.die = function () {
if (!self.isDead) {
self.isDead = true;
LK.getSound('hit').play();
// Death animation
tween(birdGraphics, {
rotation: Math.PI,
alpha: 0.7
}, {
duration: 1000
});
tween(self, {
y: 2732 - 150 - 30
}, {
duration: 1000,
easing: tween.bounceOut
});
}
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
// Add gentle floating animation
self.floatTimer = Math.random() * Math.PI * 2;
cloudGraphics.scaleX = 0.8 + Math.random() * 0.4;
cloudGraphics.scaleY = 0.8 + Math.random() * 0.4;
self.speed = -1;
self.update = function () {
self.x += self.speed;
self.floatTimer += 0.02;
cloudGraphics.y = Math.sin(self.floatTimer) * 3;
};
return self;
});
var Pipe = Container.expand(function () {
var self = Container.call(this);
self.gapSize = 480;
self.speed = -4;
self.scored = false;
// Top pipe - extends from top of screen to gap
var topPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0
});
// Bottom pipe - extends from gap to bottom of screen
var bottomPipe = self.attachAsset('pipe', {
anchorX: 0.5,
anchorY: 0
});
// Create hitbox containers that will match the visible pipe areas
self.topHitbox = self.addChild(LK.getAsset('pipe', {
anchorX: 0.5,
anchorY: 0,
alpha: 0 // Invisible hitbox
}));
self.bottomHitbox = self.addChild(LK.getAsset('pipe', {
anchorX: 0.5,
anchorY: 0,
alpha: 0 // Invisible hitbox
}));
self.setGapPosition = function (gapY) {
// Position top pipe to end at gap start
topPipe.y = 0;
topPipe.scaleY = (gapY - self.gapSize / 2) / topPipe.height;
// Position bottom pipe to start at gap end
bottomPipe.y = gapY + self.gapSize / 2;
bottomPipe.scaleY = (2732 - 150 - (gapY + self.gapSize / 2)) / bottomPipe.height;
// Update hitboxes to match visible pipe areas
self.topHitbox.y = 0;
self.topHitbox.scaleY = (gapY - self.gapSize / 2) / self.topHitbox.height;
self.topHitbox.scaleX = topPipe.scaleX;
self.bottomHitbox.y = gapY + self.gapSize / 2;
self.bottomHitbox.scaleY = (2732 - 150 - (gapY + self.gapSize / 2)) / self.bottomHitbox.height;
self.bottomHitbox.scaleX = bottomPipe.scaleX;
};
// Custom intersects method that checks both hitboxes
self.intersects = function (other) {
return self.topHitbox.intersects(other) || self.bottomHitbox.intersects(other);
};
self.update = function () {
self.x += self.speed;
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
// Twinkling effect
self.twinkleTimer = Math.random() * Math.PI * 2;
self.update = function () {
self.twinkleTimer += 0.1;
starGraphics.alpha = 0.5 + Math.sin(self.twinkleTimer) * 0.5;
};
return self;
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var sunGraphics = self.attachAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
});
// Gentle pulsing animation
self.pulseTimer = 0;
self.update = function () {
self.pulseTimer += 0.05;
sunGraphics.scaleX = 1 + Math.sin(self.pulseTimer) * 0.1;
sunGraphics.scaleY = 1 + Math.sin(self.pulseTimer) * 0.1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
// Sky backgrounds with gradient-like colors
// Deep sky blue
// Sunset pink
// Night dark blue
// Bird with better proportions and color
// Bright orange bird
// Fluffy white clouds
// Soft white clouds
// Textured ground
// Grass green ground
// Pipes with better color scheme
// Teal pipe color
// Additional decorative elements
// Yellow sun
// Small stars for night
var bird;
var pipes = [];
var clouds = [];
var ground;
var backgroundSystem;
var gameStarted = false;
var gameWaitingToStart = true;
var pipeSpawnTimer = 0;
var cloudSpawnTimer = 0;
var difficultyTimer = 0;
// UI
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 100;
var instructionTxt = new Text2('TAP TO FLAP', {
size: 80,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionTxt);
// Initialize background system
backgroundSystem = game.addChild(new Background());
// Create ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - 150
}));
// Create bird
bird = game.addChild(new Bird());
bird.x = 300;
bird.y = 1366;
bird.isDead = true; // Start in idle state until game begins
// Initial clouds
for (var i = 0; i < 3; i++) {
var cloud = game.addChild(new Cloud());
cloud.x = Math.random() * 2048;
cloud.y = Math.random() * 800 + 200;
cloud.alpha = 0.7;
clouds.push(cloud);
}
function startGame() {
if (!gameStarted && gameWaitingToStart) {
gameStarted = true;
gameWaitingToStart = false;
instructionTxt.visible = false;
pipeSpawnTimer = 0; // Reset timer so first pipe appears at correct timing
LK.playMusic('background_music');
}
}
function spawnPipe() {
var pipe = game.addChild(new Pipe());
pipe.x = 2048 + 60;
// Dynamic difficulty - reduce gap size over time
var difficultyFactor = Math.min(LK.getScore() * 0.02, 0.3);
pipe.gapSize = Math.max(430 - difficultyFactor * 100, 360);
// Randomize gap position with more variation - ensure gap stays within playable area
var minGapY = pipe.gapSize / 2 + 200; // Minimum distance from top
var maxGapY = 2732 - 150 - pipe.gapSize / 2 - 200; // Maximum distance from ground
var gapY = Math.random() * (maxGapY - minGapY) + minGapY;
pipe.setGapPosition(gapY);
pipes.push(pipe);
}
function spawnCloud() {
var cloud = game.addChild(new Cloud());
cloud.x = 2048 + 100;
cloud.y = Math.random() * 1000 + 200;
cloud.alpha = 0.6;
cloud.scaleX = Math.random() * 0.5 + 0.5;
cloud.scaleY = Math.random() * 0.5 + 0.5;
clouds.push(cloud);
}
// Game input
game.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
bird.isDead = false; // Activate bird when game starts
}
if (gameStarted) {
bird.flap();
}
};
// Game update loop
game.update = function () {
// Update background system
backgroundSystem.update();
if (gameStarted && !bird.isDead && !gameWaitingToStart) {
// Spawn pipes
pipeSpawnTimer++;
if (pipeSpawnTimer >= 210) {
// Every 3.5 seconds
pipeSpawnTimer = 0;
spawnPipe();
}
// Spawn clouds
cloudSpawnTimer++;
if (cloudSpawnTimer >= 240) {
// Every 4 seconds
cloudSpawnTimer = 0;
spawnCloud();
}
// Update and check pipes
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
// Check for scoring
if (!pipe.scored && pipe.x + 60 < bird.x) {
pipe.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
LK.getSound('score').play();
}
// Check collision with bird
if (pipe.intersects(bird)) {
bird.die();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver(); // Immediate game over when touching pipe
}
// Remove off-screen pipes
if (pipe.x < -150) {
pipe.destroy();
pipes.splice(i, 1);
}
}
// Update and manage clouds
for (var j = clouds.length - 1; j >= 0; j--) {
var cloud = clouds[j];
if (cloud.x < -250) {
cloud.destroy();
clouds.splice(j, 1);
}
}
}
// Show game over immediately when bird dies from hitting ground
if (bird.isDead && bird.y >= 2732 - 150 - 30) {
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
}
};