/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
self.speedX = 5;
self.lastX = 0;
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Store last position for edge detection
self.lastX = self.x;
// Move horizontally
self.x += self.speedX;
// Apply gravity
if (!self.speedY) self.speedY = 0;
self.speedY += 0.8; // Gravity acceleration
self.y += self.speedY;
// Keep bird within screen bounds
if (self.y < 30) {
self.y = 30;
self.speedY = 0;
}
// Create trail effect when bird has showTrail enabled (after bomb collision)
if (self.showTrail) {
if (Math.random() < 0.5) {
// 50% chance each frame when showTrail is active
var trail = LK.getAsset('bird', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: birdGraphics.scaleX * 0.7,
scaleY: 0.7,
alpha: 0.4,
tint: 0x000000 // Black trail for bomb effect
});
trail.x = self.x - (self.speedX > 0 ? 30 : -30);
trail.y = self.y + (Math.random() - 0.5) * 20;
game.addChild(trail);
// Fade out trail
tween(trail, {
alpha: 0,
scaleX: trail.scaleX * 0.5,
scaleY: trail.scaleY * 0.5
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
}
});
}
}
// Reverse direction when hitting screen edges and add scoring
if (self.lastX <= 2048 - 40 && self.x > 2048 - 40) {
self.x = 2048 - 40;
self.speedX = -self.speedX; // Reverse horizontal direction
// Play coon sound when touching edge
LK.getSound('Coon').play();
// Flip bird image horizontally using scaleX
birdGraphics.scaleX = self.speedX > 0 ? 1 : -1;
// Reset rotation to 0 when changing direction
birdGraphics.rotation = 0;
// Add point and increase speed
LK.setScore(LK.getScore() + 1);
updateScoreText(LK.getScore());
// Increase speed with smaller increment
var newSpeed = Math.abs(self.speedX) + 0.5;
if (self.speedX < 0) newSpeed = -newSpeed;
tween(self, {
speedX: newSpeed
}, {
duration: 500,
easing: tween.easeOut
});
// Increase parachute speed slightly
if (parachutes) {
for (var i = 0; i < parachutes.length; i++) {
if (parachutes[i] && !parachutes[i].destroyed) {
parachutes[i].maxSpeed += 0.2;
parachutes[i].gravity += 0.01;
}
}
}
} else if (self.lastX >= 40 && self.x < 40) {
self.x = 40;
self.speedX = -self.speedX; // Reverse horizontal direction
// Play coon sound when touching edge
LK.getSound('Coon').play();
// Flip bird image horizontally using scaleX
birdGraphics.scaleX = self.speedX > 0 ? 1 : -1;
// Reset rotation to 0 when changing direction
birdGraphics.rotation = 0;
// Add point and increase speed
LK.setScore(LK.getScore() + 1);
updateScoreText(LK.getScore());
// Increase speed with smaller increment
var newSpeed = Math.abs(self.speedX) + 0.5;
if (self.speedX < 0) newSpeed = -newSpeed;
tween(self, {
speedX: newSpeed
}, {
duration: 500,
easing: tween.easeOut
});
// Increase parachute speed slightly
if (parachutes) {
for (var i = 0; i < parachutes.length; i++) {
if (parachutes[i] && !parachutes[i].destroyed) {
parachutes[i].maxSpeed += 0.2;
parachutes[i].gravity += 0.01;
}
}
}
}
};
self.propelUp = function () {
if (!self.speedY) self.speedY = 0;
self.speedY = -15; // Upward thrust velocity
// Increase speed slightly when touching screen (like touching edges)
var currentSpeed = Math.abs(self.speedX);
var newSpeed = currentSpeed + 0.3; // Smaller increment than edge touch
if (self.speedX < 0) newSpeed = -newSpeed;
tween(self, {
speedX: newSpeed
}, {
duration: 300,
easing: tween.easeOut
});
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('Nubes', {
anchorX: 0.5,
anchorY: 0.5
});
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
// Remove cloud when it goes off screen
if (self.lastY <= 2732 + 350 && self.y > 2732 + 350) {
self.destroy();
}
};
return self;
});
var MenuBird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.speedX = 2 + Math.random() * 3; // Random speed between 2-5
self.speedY = (Math.random() - 0.5) * 2; // Random vertical movement
self.amplitude = 50 + Math.random() * 100; // Wing flap amplitude
self.frequency = 0.02 + Math.random() * 0.03; // Wing flap frequency
self.timeOffset = Math.random() * Math.PI * 2; // Random starting phase
self.time = 0;
self.update = function () {
// Move horizontally
self.x += self.speedX;
// Add flapping motion (sine wave)
self.time += self.frequency;
self.y += Math.sin(self.time + self.timeOffset) * 2;
// Add slight rotation for natural movement
birdGraphics.rotation = Math.sin(self.time + self.timeOffset) * 0.1;
// Reset position when off screen
if (self.x > 2048 + 100) {
self.x = -100;
self.y = 200 + Math.random() * 1500; // Random height
self.speedX = 2 + Math.random() * 3; // New random speed
}
};
return self;
});
var Parachute = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('Bombas', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
self.speedY = 0;
self.maxSpeed = 3; // Terminal velocity for parachute
self.gravity = 0.1; // Reduced gravity for parachute effect
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
// Apply parachute physics - slower acceleration and terminal velocity
self.speedY += self.gravity;
if (self.speedY > self.maxSpeed) {
self.speedY = self.maxSpeed; // Cap at terminal velocity
}
self.y += self.speedY;
// Add slight horizontal drift for realism
self.x += Math.sin(self.y * 0.01) * 0.5;
// Remove parachute when it goes off screen
if (self.lastY <= 2732 + 100 && self.y > 2732 + 100) {
self.destroy();
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.lastY = 0;
self.speedY = 2;
// Create pulsing star effect
self.pulseDirection = 1;
self.pulseSpeed = 0.05;
// Initialize rainbow effect properties
self.colorIndex = 0;
self.rainbowColors = [0xFF0000,
// Red
0xFF7F00,
// Orange
0xFFFF00,
// Yellow
0x00FF00,
// Green
0x0000FF,
// Blue
0x4B0082,
// Indigo
0x9400D3 // Violet
];
self.colorTimer = 0;
self.update = function () {
self.lastY = self.y;
self.y += self.speedY;
// Create pulsing effect
starGraphics.scaleX += self.pulseSpeed * self.pulseDirection;
starGraphics.scaleY += self.pulseSpeed * self.pulseDirection;
if (starGraphics.scaleX >= 2) {
self.pulseDirection = -1;
} else if (starGraphics.scaleX <= 1) {
self.pulseDirection = 1;
}
// Rotate star
starGraphics.rotation += 0.1;
// Rainbow color cycling effect (like Mario Bros star power)
self.colorTimer++;
if (self.colorTimer >= 9) {
// Change color every 9 frames (about 150ms at 60fps)
self.colorIndex = (self.colorIndex + 1) % self.rainbowColors.length;
starGraphics.tint = self.rainbowColors[self.colorIndex];
self.colorTimer = 0;
}
// Remove when off screen
if (self.lastY <= 2732 + 100 && self.y > 2732 + 100) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu' or 'playing'
var menuContainer;
var gameContainer;
// Create menu container
menuContainer = new Container();
game.addChild(menuContainer);
// Create game container (will be hidden initially)
gameContainer = new Container();
game.addChild(gameContainer);
// Add sky background that covers full screen
var skyBackground = game.attachAsset('Cielo', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
// Add background to menu
menuContainer.addChild(skyBackground);
// Create logo
var logoAsset = LK.getAsset('Logo', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
logoAsset.x = 2048 / 2;
logoAsset.y = 800;
menuContainer.addChild(logoAsset);
// Create play button using play asset
var playButton = LK.getAsset('Play', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4
});
playButton.x = 2048 / 2;
playButton.y = 1500;
menuContainer.addChild(playButton);
// Create instructions
var instructionsTxt = new Text2('Tap to fly and avoid bombs!\nCollect stars for power-ups!', {
size: 80,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x000000,
strokeThickness: 6
});
instructionsTxt.anchor.set(0.5, 0.5);
instructionsTxt.x = 2048 / 2;
instructionsTxt.y = 2000;
menuContainer.addChild(instructionsTxt);
// Add pulsing animation to play button
tween(playButton, {
scaleX: 4.5,
scaleY: 4.5
}, {
duration: 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
// Hide game container initially
gameContainer.visible = false;
// Create flying birds for menu scene
var menuBirds = [];
for (var i = 0; i < 5; i++) {
var menuBird = new MenuBird();
menuBird.x = -100 - i * 200; // Stagger starting positions
menuBird.y = 200 + Math.random() * 1500; // Random height
menuContainer.addChild(menuBird);
menuBirds.push(menuBird);
// Add slight tween animation for variety
tween(menuBird, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeInOut,
yoyo: true,
loop: true
});
}
// Create game background for game container
var gameBackground = game.attachAsset('Cielo', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
gameContainer.addChild(gameBackground);
// Create score display
var scoreTxt = new Text2('0', {
size: 180,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x000000,
strokeThickness: 15
});
scoreTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreTxt);
scoreTxt.y = -50;
scoreTxt.visible = false; // Hide score in menu
// Function to update score text with consistent styling
function updateScoreText(score) {
scoreTxt.setText(score);
scoreTxt.stroke = 0x000000;
scoreTxt.strokeThickness = 15;
}
// Game initialization function
function initializeGame() {
// Reset game state
LK.setScore(0);
updateScoreText(0);
bombHit = false;
isInvincible = false;
clouds = [];
parachutes = [];
powerUps = [];
lastParachuteSpawn = 0;
lastPowerUpSpawn = Date.now();
invincibilityEndTime = 0;
powerUpCooldownEndTime = 0;
// Create bird
bird = new Bird();
bird.x = 300;
bird.y = 2732 / 2;
bird.tint = 0xFFFFFF;
bird.showTrail = false;
gameContainer.addChild(bird);
// Gradually increase bird speed over time
tween(bird, {
speedX: 15
}, {
duration: 30000,
easing: tween.easeInOut
});
// Instruction text
var instructionTxt = new Text2('Tap to propel the bird upward!', {
size: 60,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x000000,
strokeThickness: 4
});
instructionTxt.anchor.set(0.5, 0.5);
gameContainer.addChild(instructionTxt);
instructionTxt.x = 2048 / 2;
instructionTxt.y = 300;
}
// Variables that will be initialized in initializeGame
var bird;
var clouds = [];
var parachutes = [];
var powerUps = [];
var lastParachuteSpawn = 0;
var parachuteSpawnDelay = 1000 + Math.random() * 2000;
var lastPowerUpSpawn = Date.now();
var powerUpSpawnDelay = 30000 + Math.random() * 20000;
var isInvincible = false;
var invincibilityEndTime = 0;
var powerUpCooldownEndTime = 0;
var bombHit = false;
// Touch controls
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if play button was clicked
var playButtonBounds = {
left: 2048 / 2 - 260,
// Play button width approximation (130 * 4 scale = 520 / 2 = 260)
right: 2048 / 2 + 260,
top: 1500 - 187,
// Play button height approximation (93.44 * 4 scale = 373.76 / 2 = 187)
bottom: 1500 + 187
};
if (x >= playButtonBounds.left && x <= playButtonBounds.right && y >= playButtonBounds.top && y <= playButtonBounds.bottom) {
// Stop current pulsing animation
tween.stop(playButton, {
scaleX: true,
scaleY: true
});
// Scale up then down animation
tween(playButton, {
scaleX: 5.5,
scaleY: 5.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 4,
scaleY: 4
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
// Create black overlay for transition
var blackOverlay = LK.getAsset('Cielo', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
tint: 0x000000,
alpha: 0
});
game.addChild(blackOverlay);
// Fade to black
tween(blackOverlay, {
alpha: 1
}, {
duration: 1300,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Wait 3 seconds in black
LK.setTimeout(function () {
// Start game
gameState = 'playing';
menuContainer.visible = false;
gameContainer.visible = true;
scoreTxt.visible = true;
initializeGame();
// Fade back to normal
tween(blackOverlay, {
alpha: 0
}, {
duration: 1300,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Remove overlay when transition is complete
blackOverlay.destroy();
}
});
}, 3000);
}
});
}
return;
}
// Game controls (only when playing)
if (gameState === 'playing') {
// Don't allow touch input when bird is hit by bomb
if (bombHit) {
return;
}
bird.propelUp();
// Play flap sound when touching screen
LK.getSound('Flap').play();
// Add rotation effect for jump to bird graphics only
var birdGraphics = bird.children[0];
// Rotate upward when moving left, downward when moving right
var rotationDirection = bird.speedX < 0 ? 0.3 : -0.3;
tween(birdGraphics, {
rotation: birdGraphics.rotation + rotationDirection
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to normal rotation
tween(birdGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
game.update = function () {
// Update menu birds when in menu state
if (gameState === 'menu') {
for (var i = 0; i < menuBirds.length; i++) {
if (menuBirds[i] && !menuBirds[i].destroyed) {
menuBirds[i].update();
}
}
return;
}
// Only run game logic when in playing state
if (gameState !== 'playing') {
return;
}
// Spawn clouds randomly - one at a time
if (Math.random() < 0.001) {
// 0.1% chance each frame
var newCloud = new Cloud();
newCloud.x = Math.random() * 2048; // Random X position across screen width
newCloud.y = -50; // Start above screen
newCloud.lastY = newCloud.y;
clouds.push(newCloud);
game.addChild(newCloud);
// Animate cloud falling down with random speed
var fallDuration = 8000 + Math.random() * 4000; // 8-12 seconds
tween(newCloud, {
y: 2732 + 300
}, {
duration: fallDuration,
easing: tween.linear,
onFinish: function onFinish() {
// Remove from clouds array when finished
for (var i = clouds.length - 1; i >= 0; i--) {
if (clouds[i] === newCloud) {
clouds.splice(i, 1);
break;
}
}
}
});
}
// Spawn parachutes with timing control - multiple can exist
var currentTime = Date.now();
if (currentTime - lastParachuteSpawn > parachuteSpawnDelay) {
var newParachute = new Parachute();
newParachute.x = Math.random() * (2048 - 200) + 100; // Random X position with margin
newParachute.y = -100; // Start above screen
newParachute.lastY = newParachute.y;
parachutes.push(newParachute);
game.addChild(newParachute);
lastParachuteSpawn = currentTime;
// Set new random delay for next spawn (3-7 seconds)
parachuteSpawnDelay = 3000 + Math.random() * 4000;
}
// Spawn power-ups occasionally (only if not invincible and cooldown has passed)
if (!isInvincible && currentTime > powerUpCooldownEndTime && currentTime - lastPowerUpSpawn > powerUpSpawnDelay) {
var newPowerUp = new PowerUp();
newPowerUp.x = Math.random() * (2048 - 200) + 100;
newPowerUp.y = -100;
newPowerUp.lastY = newPowerUp.y;
powerUps.push(newPowerUp);
game.addChild(newPowerUp);
lastPowerUpSpawn = currentTime;
// Set new random delay for next spawn (30-50 seconds)
powerUpSpawnDelay = 30000 + Math.random() * 20000;
}
// Check invincibility timer
if (isInvincible && currentTime > invincibilityEndTime) {
isInvincible = false;
// Stop any ongoing tween effects on bird
tween.stop(bird, {
tint: true
});
bird.tint = 0xFFFFFF; // Reset to normal color
// Stop Estrella music when power-up ends
LK.stopMusic();
// Set cooldown period (10-15 seconds) before next power-up can spawn
powerUpCooldownEndTime = currentTime + 10000 + Math.random() * 5000;
}
// Check power-up collection
var _loop = function _loop() {
powerUp = powerUps[i];
if (!powerUp.destroyed && bird.intersects(powerUp)) {
// 60 seconds of invincibility
// Start Mario-like rainbow color cycling effect
var colorIndex = 0;
var rainbowColors = [0xFF0000,
// Red
0xFF7F00,
// Orange
0xFFFF00,
// Yellow
0x00FF00,
// Green
0x0000FF,
// Blue
0x4B0082,
// Indigo
0x9400D3 // Violet
];
var _createRainbowEffect = function createRainbowEffect() {
if (isInvincible) {
tween(bird, {
tint: rainbowColors[colorIndex]
}, {
duration: 150,
onFinish: function onFinish() {
if (isInvincible) {
colorIndex = (colorIndex + 1) % rainbowColors.length;
_createRainbowEffect();
}
}
});
}
};
// Activate invincibility
isInvincible = true;
invincibilityEndTime = currentTime + 60000;
_createRainbowEffect();
// Play Estrella music for power-up
LK.playMusic('Estrella');
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
return 1; // break
}
},
powerUp;
for (var i = powerUps.length - 1; i >= 0; i--) {
if (_loop()) break;
}
// Clean up destroyed clouds from array
for (var i = clouds.length - 1; i >= 0; i--) {
if (clouds[i].destroyed) {
clouds.splice(i, 1);
}
}
// Check collision between bird and parachutes
for (var i = parachutes.length - 1; i >= 0; i--) {
var parachute = parachutes[i];
if (!parachute.destroyed && bird.intersects(parachute)) {
if (isInvincible) {
// If invincible, just destroy the bomb without explosion
parachute.destroy();
parachutes.splice(i, 1);
// Add bonus points for destroying bomb while invincible
LK.setScore(LK.getScore() + 5);
updateScoreText(LK.getScore());
} else {
// Hide the bomb
parachute.visible = false;
// Play explosion sound
LK.getSound('Explosion').play();
// Make bird turn black
bird.tint = 0x000000;
// Make bird fall by giving it strong downward velocity
bird.speedY = 10; // Strong downward velocity
// Enable trail effect for the bird after bomb collision
bird.showTrail = true;
// Disable touch input when bird is hit by bomb
bombHit = true;
// Create explosion at bomb position
var explosion = game.attachAsset('Explosion', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
explosion.x = parachute.x;
explosion.y = parachute.y;
// Animate explosion
tween(explosion, {
scaleX: 5,
scaleY: 5,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut
});
// Remove parachute
parachute.destroy();
parachutes.splice(i, 1);
}
break; // Only handle one collision per frame
}
}
// Check if bird falls below screen for game over
if (bird.y > 2732 + 100) {
// Only show game over if bird was hit by bomb (has showTrail) or falls naturally
if (bird.showTrail || bird.tint === 0x000000) {
// Wait 1 second before showing game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
} else {
// Wait 1 second before showing game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Clean up destroyed parachutes from array
for (var i = parachutes.length - 1; i >= 0; i--) {
if (parachutes[i].destroyed) {
parachutes.splice(i, 1);
}
}
// Clean up destroyed power-ups from array
for (var i = powerUps.length - 1; i >= 0; i--) {
if (powerUps[i].destroyed) {
powerUps.splice(i, 1);
}
}
};
; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
self.speedX = 5;
self.lastX = 0;
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Store last position for edge detection
self.lastX = self.x;
// Move horizontally
self.x += self.speedX;
// Apply gravity
if (!self.speedY) self.speedY = 0;
self.speedY += 0.8; // Gravity acceleration
self.y += self.speedY;
// Keep bird within screen bounds
if (self.y < 30) {
self.y = 30;
self.speedY = 0;
}
// Create trail effect when bird has showTrail enabled (after bomb collision)
if (self.showTrail) {
if (Math.random() < 0.5) {
// 50% chance each frame when showTrail is active
var trail = LK.getAsset('bird', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: birdGraphics.scaleX * 0.7,
scaleY: 0.7,
alpha: 0.4,
tint: 0x000000 // Black trail for bomb effect
});
trail.x = self.x - (self.speedX > 0 ? 30 : -30);
trail.y = self.y + (Math.random() - 0.5) * 20;
game.addChild(trail);
// Fade out trail
tween(trail, {
alpha: 0,
scaleX: trail.scaleX * 0.5,
scaleY: trail.scaleY * 0.5
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
trail.destroy();
}
});
}
}
// Reverse direction when hitting screen edges and add scoring
if (self.lastX <= 2048 - 40 && self.x > 2048 - 40) {
self.x = 2048 - 40;
self.speedX = -self.speedX; // Reverse horizontal direction
// Play coon sound when touching edge
LK.getSound('Coon').play();
// Flip bird image horizontally using scaleX
birdGraphics.scaleX = self.speedX > 0 ? 1 : -1;
// Reset rotation to 0 when changing direction
birdGraphics.rotation = 0;
// Add point and increase speed
LK.setScore(LK.getScore() + 1);
updateScoreText(LK.getScore());
// Increase speed with smaller increment
var newSpeed = Math.abs(self.speedX) + 0.5;
if (self.speedX < 0) newSpeed = -newSpeed;
tween(self, {
speedX: newSpeed
}, {
duration: 500,
easing: tween.easeOut
});
// Increase parachute speed slightly
if (parachutes) {
for (var i = 0; i < parachutes.length; i++) {
if (parachutes[i] && !parachutes[i].destroyed) {
parachutes[i].maxSpeed += 0.2;
parachutes[i].gravity += 0.01;
}
}
}
} else if (self.lastX >= 40 && self.x < 40) {
self.x = 40;
self.speedX = -self.speedX; // Reverse horizontal direction
// Play coon sound when touching edge
LK.getSound('Coon').play();
// Flip bird image horizontally using scaleX
birdGraphics.scaleX = self.speedX > 0 ? 1 : -1;
// Reset rotation to 0 when changing direction
birdGraphics.rotation = 0;
// Add point and increase speed
LK.setScore(LK.getScore() + 1);
updateScoreText(LK.getScore());
// Increase speed with smaller increment
var newSpeed = Math.abs(self.speedX) + 0.5;
if (self.speedX < 0) newSpeed = -newSpeed;
tween(self, {
speedX: newSpeed
}, {
duration: 500,
easing: tween.easeOut
});
// Increase parachute speed slightly
if (parachutes) {
for (var i = 0; i < parachutes.length; i++) {
if (parachutes[i] && !parachutes[i].destroyed) {
parachutes[i].maxSpeed += 0.2;
parachutes[i].gravity += 0.01;
}
}
}
}
};
self.propelUp = function () {
if (!self.speedY) self.speedY = 0;
self.speedY = -15; // Upward thrust velocity
// Increase speed slightly when touching screen (like touching edges)
var currentSpeed = Math.abs(self.speedX);
var newSpeed = currentSpeed + 0.3; // Smaller increment than edge touch
if (self.speedX < 0) newSpeed = -newSpeed;
tween(self, {
speedX: newSpeed
}, {
duration: 300,
easing: tween.easeOut
});
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('Nubes', {
anchorX: 0.5,
anchorY: 0.5
});
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
// Remove cloud when it goes off screen
if (self.lastY <= 2732 + 350 && self.y > 2732 + 350) {
self.destroy();
}
};
return self;
});
var MenuBird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
self.speedX = 2 + Math.random() * 3; // Random speed between 2-5
self.speedY = (Math.random() - 0.5) * 2; // Random vertical movement
self.amplitude = 50 + Math.random() * 100; // Wing flap amplitude
self.frequency = 0.02 + Math.random() * 0.03; // Wing flap frequency
self.timeOffset = Math.random() * Math.PI * 2; // Random starting phase
self.time = 0;
self.update = function () {
// Move horizontally
self.x += self.speedX;
// Add flapping motion (sine wave)
self.time += self.frequency;
self.y += Math.sin(self.time + self.timeOffset) * 2;
// Add slight rotation for natural movement
birdGraphics.rotation = Math.sin(self.time + self.timeOffset) * 0.1;
// Reset position when off screen
if (self.x > 2048 + 100) {
self.x = -100;
self.y = 200 + Math.random() * 1500; // Random height
self.speedX = 2 + Math.random() * 3; // New random speed
}
};
return self;
});
var Parachute = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('Bombas', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2
});
self.speedY = 0;
self.maxSpeed = 3; // Terminal velocity for parachute
self.gravity = 0.1; // Reduced gravity for parachute effect
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
// Apply parachute physics - slower acceleration and terminal velocity
self.speedY += self.gravity;
if (self.speedY > self.maxSpeed) {
self.speedY = self.maxSpeed; // Cap at terminal velocity
}
self.y += self.speedY;
// Add slight horizontal drift for realism
self.x += Math.sin(self.y * 0.01) * 0.5;
// Remove parachute when it goes off screen
if (self.lastY <= 2732 + 100 && self.y > 2732 + 100) {
self.destroy();
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.lastY = 0;
self.speedY = 2;
// Create pulsing star effect
self.pulseDirection = 1;
self.pulseSpeed = 0.05;
// Initialize rainbow effect properties
self.colorIndex = 0;
self.rainbowColors = [0xFF0000,
// Red
0xFF7F00,
// Orange
0xFFFF00,
// Yellow
0x00FF00,
// Green
0x0000FF,
// Blue
0x4B0082,
// Indigo
0x9400D3 // Violet
];
self.colorTimer = 0;
self.update = function () {
self.lastY = self.y;
self.y += self.speedY;
// Create pulsing effect
starGraphics.scaleX += self.pulseSpeed * self.pulseDirection;
starGraphics.scaleY += self.pulseSpeed * self.pulseDirection;
if (starGraphics.scaleX >= 2) {
self.pulseDirection = -1;
} else if (starGraphics.scaleX <= 1) {
self.pulseDirection = 1;
}
// Rotate star
starGraphics.rotation += 0.1;
// Rainbow color cycling effect (like Mario Bros star power)
self.colorTimer++;
if (self.colorTimer >= 9) {
// Change color every 9 frames (about 150ms at 60fps)
self.colorIndex = (self.colorIndex + 1) % self.rainbowColors.length;
starGraphics.tint = self.rainbowColors[self.colorIndex];
self.colorTimer = 0;
}
// Remove when off screen
if (self.lastY <= 2732 + 100 && self.y > 2732 + 100) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state management
var gameState = 'menu'; // 'menu' or 'playing'
var menuContainer;
var gameContainer;
// Create menu container
menuContainer = new Container();
game.addChild(menuContainer);
// Create game container (will be hidden initially)
gameContainer = new Container();
game.addChild(gameContainer);
// Add sky background that covers full screen
var skyBackground = game.attachAsset('Cielo', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
// Add background to menu
menuContainer.addChild(skyBackground);
// Create logo
var logoAsset = LK.getAsset('Logo', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
logoAsset.x = 2048 / 2;
logoAsset.y = 800;
menuContainer.addChild(logoAsset);
// Create play button using play asset
var playButton = LK.getAsset('Play', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4
});
playButton.x = 2048 / 2;
playButton.y = 1500;
menuContainer.addChild(playButton);
// Create instructions
var instructionsTxt = new Text2('Tap to fly and avoid bombs!\nCollect stars for power-ups!', {
size: 80,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x000000,
strokeThickness: 6
});
instructionsTxt.anchor.set(0.5, 0.5);
instructionsTxt.x = 2048 / 2;
instructionsTxt.y = 2000;
menuContainer.addChild(instructionsTxt);
// Add pulsing animation to play button
tween(playButton, {
scaleX: 4.5,
scaleY: 4.5
}, {
duration: 1000,
easing: tween.easeInOut,
loop: true,
yoyo: true
});
// Hide game container initially
gameContainer.visible = false;
// Create flying birds for menu scene
var menuBirds = [];
for (var i = 0; i < 5; i++) {
var menuBird = new MenuBird();
menuBird.x = -100 - i * 200; // Stagger starting positions
menuBird.y = 200 + Math.random() * 1500; // Random height
menuContainer.addChild(menuBird);
menuBirds.push(menuBird);
// Add slight tween animation for variety
tween(menuBird, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 2000 + Math.random() * 2000,
easing: tween.easeInOut,
yoyo: true,
loop: true
});
}
// Create game background for game container
var gameBackground = game.attachAsset('Cielo', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
gameContainer.addChild(gameBackground);
// Create score display
var scoreTxt = new Text2('0', {
size: 180,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x000000,
strokeThickness: 15
});
scoreTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(scoreTxt);
scoreTxt.y = -50;
scoreTxt.visible = false; // Hide score in menu
// Function to update score text with consistent styling
function updateScoreText(score) {
scoreTxt.setText(score);
scoreTxt.stroke = 0x000000;
scoreTxt.strokeThickness = 15;
}
// Game initialization function
function initializeGame() {
// Reset game state
LK.setScore(0);
updateScoreText(0);
bombHit = false;
isInvincible = false;
clouds = [];
parachutes = [];
powerUps = [];
lastParachuteSpawn = 0;
lastPowerUpSpawn = Date.now();
invincibilityEndTime = 0;
powerUpCooldownEndTime = 0;
// Create bird
bird = new Bird();
bird.x = 300;
bird.y = 2732 / 2;
bird.tint = 0xFFFFFF;
bird.showTrail = false;
gameContainer.addChild(bird);
// Gradually increase bird speed over time
tween(bird, {
speedX: 15
}, {
duration: 30000,
easing: tween.easeInOut
});
// Instruction text
var instructionTxt = new Text2('Tap to propel the bird upward!', {
size: 60,
fill: 0xFFFFFF,
font: "'Arial Black', Arial, sans-serif",
stroke: 0x000000,
strokeThickness: 4
});
instructionTxt.anchor.set(0.5, 0.5);
gameContainer.addChild(instructionTxt);
instructionTxt.x = 2048 / 2;
instructionTxt.y = 300;
}
// Variables that will be initialized in initializeGame
var bird;
var clouds = [];
var parachutes = [];
var powerUps = [];
var lastParachuteSpawn = 0;
var parachuteSpawnDelay = 1000 + Math.random() * 2000;
var lastPowerUpSpawn = Date.now();
var powerUpSpawnDelay = 30000 + Math.random() * 20000;
var isInvincible = false;
var invincibilityEndTime = 0;
var powerUpCooldownEndTime = 0;
var bombHit = false;
// Touch controls
game.down = function (x, y, obj) {
if (gameState === 'menu') {
// Check if play button was clicked
var playButtonBounds = {
left: 2048 / 2 - 260,
// Play button width approximation (130 * 4 scale = 520 / 2 = 260)
right: 2048 / 2 + 260,
top: 1500 - 187,
// Play button height approximation (93.44 * 4 scale = 373.76 / 2 = 187)
bottom: 1500 + 187
};
if (x >= playButtonBounds.left && x <= playButtonBounds.right && y >= playButtonBounds.top && y <= playButtonBounds.bottom) {
// Stop current pulsing animation
tween.stop(playButton, {
scaleX: true,
scaleY: true
});
// Scale up then down animation
tween(playButton, {
scaleX: 5.5,
scaleY: 5.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 4,
scaleY: 4
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
// Create black overlay for transition
var blackOverlay = LK.getAsset('Cielo', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732,
tint: 0x000000,
alpha: 0
});
game.addChild(blackOverlay);
// Fade to black
tween(blackOverlay, {
alpha: 1
}, {
duration: 1300,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Wait 3 seconds in black
LK.setTimeout(function () {
// Start game
gameState = 'playing';
menuContainer.visible = false;
gameContainer.visible = true;
scoreTxt.visible = true;
initializeGame();
// Fade back to normal
tween(blackOverlay, {
alpha: 0
}, {
duration: 1300,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Remove overlay when transition is complete
blackOverlay.destroy();
}
});
}, 3000);
}
});
}
return;
}
// Game controls (only when playing)
if (gameState === 'playing') {
// Don't allow touch input when bird is hit by bomb
if (bombHit) {
return;
}
bird.propelUp();
// Play flap sound when touching screen
LK.getSound('Flap').play();
// Add rotation effect for jump to bird graphics only
var birdGraphics = bird.children[0];
// Rotate upward when moving left, downward when moving right
var rotationDirection = bird.speedX < 0 ? 0.3 : -0.3;
tween(birdGraphics, {
rotation: birdGraphics.rotation + rotationDirection
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to normal rotation
tween(birdGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
game.update = function () {
// Update menu birds when in menu state
if (gameState === 'menu') {
for (var i = 0; i < menuBirds.length; i++) {
if (menuBirds[i] && !menuBirds[i].destroyed) {
menuBirds[i].update();
}
}
return;
}
// Only run game logic when in playing state
if (gameState !== 'playing') {
return;
}
// Spawn clouds randomly - one at a time
if (Math.random() < 0.001) {
// 0.1% chance each frame
var newCloud = new Cloud();
newCloud.x = Math.random() * 2048; // Random X position across screen width
newCloud.y = -50; // Start above screen
newCloud.lastY = newCloud.y;
clouds.push(newCloud);
game.addChild(newCloud);
// Animate cloud falling down with random speed
var fallDuration = 8000 + Math.random() * 4000; // 8-12 seconds
tween(newCloud, {
y: 2732 + 300
}, {
duration: fallDuration,
easing: tween.linear,
onFinish: function onFinish() {
// Remove from clouds array when finished
for (var i = clouds.length - 1; i >= 0; i--) {
if (clouds[i] === newCloud) {
clouds.splice(i, 1);
break;
}
}
}
});
}
// Spawn parachutes with timing control - multiple can exist
var currentTime = Date.now();
if (currentTime - lastParachuteSpawn > parachuteSpawnDelay) {
var newParachute = new Parachute();
newParachute.x = Math.random() * (2048 - 200) + 100; // Random X position with margin
newParachute.y = -100; // Start above screen
newParachute.lastY = newParachute.y;
parachutes.push(newParachute);
game.addChild(newParachute);
lastParachuteSpawn = currentTime;
// Set new random delay for next spawn (3-7 seconds)
parachuteSpawnDelay = 3000 + Math.random() * 4000;
}
// Spawn power-ups occasionally (only if not invincible and cooldown has passed)
if (!isInvincible && currentTime > powerUpCooldownEndTime && currentTime - lastPowerUpSpawn > powerUpSpawnDelay) {
var newPowerUp = new PowerUp();
newPowerUp.x = Math.random() * (2048 - 200) + 100;
newPowerUp.y = -100;
newPowerUp.lastY = newPowerUp.y;
powerUps.push(newPowerUp);
game.addChild(newPowerUp);
lastPowerUpSpawn = currentTime;
// Set new random delay for next spawn (30-50 seconds)
powerUpSpawnDelay = 30000 + Math.random() * 20000;
}
// Check invincibility timer
if (isInvincible && currentTime > invincibilityEndTime) {
isInvincible = false;
// Stop any ongoing tween effects on bird
tween.stop(bird, {
tint: true
});
bird.tint = 0xFFFFFF; // Reset to normal color
// Stop Estrella music when power-up ends
LK.stopMusic();
// Set cooldown period (10-15 seconds) before next power-up can spawn
powerUpCooldownEndTime = currentTime + 10000 + Math.random() * 5000;
}
// Check power-up collection
var _loop = function _loop() {
powerUp = powerUps[i];
if (!powerUp.destroyed && bird.intersects(powerUp)) {
// 60 seconds of invincibility
// Start Mario-like rainbow color cycling effect
var colorIndex = 0;
var rainbowColors = [0xFF0000,
// Red
0xFF7F00,
// Orange
0xFFFF00,
// Yellow
0x00FF00,
// Green
0x0000FF,
// Blue
0x4B0082,
// Indigo
0x9400D3 // Violet
];
var _createRainbowEffect = function createRainbowEffect() {
if (isInvincible) {
tween(bird, {
tint: rainbowColors[colorIndex]
}, {
duration: 150,
onFinish: function onFinish() {
if (isInvincible) {
colorIndex = (colorIndex + 1) % rainbowColors.length;
_createRainbowEffect();
}
}
});
}
};
// Activate invincibility
isInvincible = true;
invincibilityEndTime = currentTime + 60000;
_createRainbowEffect();
// Play Estrella music for power-up
LK.playMusic('Estrella');
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
return 1; // break
}
},
powerUp;
for (var i = powerUps.length - 1; i >= 0; i--) {
if (_loop()) break;
}
// Clean up destroyed clouds from array
for (var i = clouds.length - 1; i >= 0; i--) {
if (clouds[i].destroyed) {
clouds.splice(i, 1);
}
}
// Check collision between bird and parachutes
for (var i = parachutes.length - 1; i >= 0; i--) {
var parachute = parachutes[i];
if (!parachute.destroyed && bird.intersects(parachute)) {
if (isInvincible) {
// If invincible, just destroy the bomb without explosion
parachute.destroy();
parachutes.splice(i, 1);
// Add bonus points for destroying bomb while invincible
LK.setScore(LK.getScore() + 5);
updateScoreText(LK.getScore());
} else {
// Hide the bomb
parachute.visible = false;
// Play explosion sound
LK.getSound('Explosion').play();
// Make bird turn black
bird.tint = 0x000000;
// Make bird fall by giving it strong downward velocity
bird.speedY = 10; // Strong downward velocity
// Enable trail effect for the bird after bomb collision
bird.showTrail = true;
// Disable touch input when bird is hit by bomb
bombHit = true;
// Create explosion at bomb position
var explosion = game.attachAsset('Explosion', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3
});
explosion.x = parachute.x;
explosion.y = parachute.y;
// Animate explosion
tween(explosion, {
scaleX: 5,
scaleY: 5,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut
});
// Remove parachute
parachute.destroy();
parachutes.splice(i, 1);
}
break; // Only handle one collision per frame
}
}
// Check if bird falls below screen for game over
if (bird.y > 2732 + 100) {
// Only show game over if bird was hit by bomb (has showTrail) or falls naturally
if (bird.showTrail || bird.tint === 0x000000) {
// Wait 1 second before showing game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
} else {
// Wait 1 second before showing game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Clean up destroyed parachutes from array
for (var i = parachutes.length - 1; i >= 0; i--) {
if (parachutes[i].destroyed) {
parachutes.splice(i, 1);
}
}
// Clean up destroyed power-ups from array
for (var i = powerUps.length - 1; i >= 0; i--) {
if (powerUps[i].destroyed) {
powerUps.splice(i, 1);
}
}
};
;
Crea un pajaro caway en 2d viendo a la derecha de color rojo acostado que con se vean las patas. In-Game asset. No shadows
Haz una sola nube carton de color blanco. In-Game asset. High contrast. No shadows
Un paracaidas con una cja con bombas carton. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Has un cielo bonito sin nubes y sin bordes. In-Game asset. High contrast. No shadows
Explosión. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Pajaro amarillo con pico naranja carton. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
En el logo estera el texto de bird bomber abajo estara un cañon y arriba un pajaro. In-Game asset. High contrast. No shadows
Button play. In-Game asset. High contrast. No shadows