/**** * Classes ****/ var Bird = Container.expand(function () { var self = Container.call(this); var birdGraphics = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); self.xSpeed = 10.9375; self.ySpeed = -20; self.gravity = 1; self.lift = -15; self.flap = function () { self.ySpeed = self.lift * 1.5; LK.getSound('flap').play(); }; self._update_migrated = function () { if (game.isMouseDown) { self.ySpeed += self.gravity / 3; } else { self.ySpeed += self.gravity; } self.y += self.ySpeed; self.x += self.xSpeed; if (self.y <= 0 || self.y >= 2732) { self.speed = -self.speed; } var targetRotation = Math.atan2(self.ySpeed, self.xSpeed * self.scale.x) / 2; birdGraphics.rotation += (targetRotation - birdGraphics.rotation) / 10; }; self.flip = function () { self.scale.x *= -1; }; }); // Egg class var Egg = Container.expand(function () { var self = Container.call(this); var eggGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); self.ySpeed = 8; self.update = function () { self.y += self.ySpeed; // Remove egg if it falls out of screen if (self.y > 2800) { self.destroy(); if (game.eggs) { var idx = game.eggs.indexOf(self); if (idx !== -1) game.eggs.splice(idx, 1); } } }; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleShadow = self.attachAsset('obstacleShadow', { anchorX: 0.5, anchorY: 0.5 }); obstacleShadow.rotation = Math.PI / 4; var obstacleShadow2 = self.attachAsset('obstacleShadow2', { anchorX: 0.5, anchorY: 0.5 }); obstacleShadow2.rotation = Math.PI / 4; obstacleShadow2.y = -7; var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); obstacleGraphics.rotation = Math.PI / 4; self.speed = 5; self._move_migrated = function (speed) { self.y += speed; }; }); // Powerup class for floating special abilities var Powerup = Container.expand(function () { var self = Container.call(this); // Randomly pick a type var types = ['speed', 'immune']; self.type = types[Math.floor(Math.random() * types.length)]; // Use different color for each type var color = self.type === 'speed' ? 0xffd700 : 0x00ffcc; var powerupGraphics = self.attachAsset('obstacleShadow', { anchorX: 0.5, anchorY: 0.5 }); powerupGraphics.tint = color; powerupGraphics.scale.x = 0.7; powerupGraphics.scale.y = 0.7; // Add a text label for the type var label = new Text2(self.type === 'speed' ? 'S' : 'I', { size: 120, fill: '#222a9a', font: 'Impact', align: 'center' }); label.anchor.set(0.5, 0.5); self.addChild(label); self.speed = 5; self.update = function () { self.y += self.speed; // Remove if out of screen if (self.y > 2900) { self.destroy(); if (game.powerups) { var idx = game.powerups.indexOf(self); if (idx !== -1) game.powerups.splice(idx, 1); } } }; return self; }); var Wall = Container.expand(function () { var self = Container.call(this); var wallGraphics = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5 }); }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ var tutorialTextWhite = new Text2('Tap to Flap\nHold to Float', { size: 150, fill: '#ffffff', font: 'Impact', align: 'center' }); tutorialTextWhite.anchor.set(.5, 1); tutorialTextWhite.x = -4; tutorialTextWhite.y = -62; LK.gui.bottom.addChild(tutorialTextWhite); var tutorialText = new Text2('Tap to Flap\nHold to Float', { size: 150, fill: '#3a84f7', font: 'Impact', dropShadow: true, dropShadowColor: '#222a9a', dropShadowBlur: 5, dropShadowDistance: 7, dropShadowAngle: 0, align: 'center' }); tutorialText.anchor.set(.5, 1); tutorialText.y = -50; LK.gui.bottom.addChild(tutorialText); game.score = 0; game.obstacleSpeed = 5; game.obstacleSpeedIncrease = 0.005; game.checkObstacleCollision = function (obstacles) { for (var i = 0; i < obstacles.length; i++) { obstacles[i]._move_migrated(); var dist = Math.sqrt(Math.pow(bird.x - obstacles[i].x, 2) + Math.pow(bird.y - obstacles[i].y, 2)); if (dist < 280) { // If immune, skip game over if (game.powerupTimers && game.powerupTimers.immune && LK.ticks <= game.powerupTimers.immune) { continue; } LK.setScore(game.score); LK.getSound('gameOverJingle').play(); LK.showGameOver(); } } }; game.setBackgroundColor(0xadd8e6); var scoreText = new Text2('0', { size: 150, fill: '#3a84f7', font: 'Impact', dropShadow: true, dropShadowColor: '#222a9a', dropShadowBlur: 5, dropShadowDistance: 7, dropShadowAngle: 0 }); scoreText.anchor.set(.5, 0); LK.gui.top.addChild(scoreText); var scoreText2 = new Text2('0', { size: 150, fill: '#ffffff', font: 'Impact' }); scoreText2.anchor.set(.5, 0); scoreText2.x = -4; scoreText2.y = -5; LK.gui.top.addChild(scoreText2); LK.gui.top.addChild(scoreText); var bird = game.addChild(new Bird()); var leftWall = game.addChild(new Wall()); leftWall.x = 0; leftWall.y = 1366; var rightWall = game.addChild(new Wall()); rightWall.x = 2048; rightWall.y = 1366; var leftObstacles = [], rightObstacles = []; var obstacleSpawnRandomness = 120; var obstacleSpawnRandomnessDecrease = 0.025 * (2 / 3); var obstacleSpawnY = -500; var leftObstacleSpawnTime = Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness; var rightObstacleSpawnTime = Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness; bird.x = 1024; bird.y = 1366; game.isMouseDown = false; game.down = function (x, y, obj) { bird.flap(); game.isMouseDown = true; // Lay an egg at bird's position if (!game.eggs) game.eggs = []; var egg = game.addChild(new Egg()); egg.x = bird.x; egg.y = bird.y + 80; egg.scale.x = 8; egg.scale.y = 8; game.eggs.push(egg); }; game.up = function (x, y, obj) { game.isMouseDown = false; }; game.update = function () { bird._update_migrated(); if (game.score > 2) { tutorialText.y += 5; tutorialTextWhite.y += 5; } scoreText.setText(game.score); scoreText2.setText(game.score); game.obstacleSpeed += game.obstacleSpeedIncrease; obstacleSpawnRandomness -= obstacleSpawnRandomnessDecrease; if (obstacleSpawnRandomness < 20) { obstacleSpawnRandomness = 20; } if (LK.ticks >= leftObstacleSpawnTime) { var newObstacle = game.addChildAt(new Obstacle(), 0); newObstacle.x = 0; newObstacle.y = obstacleSpawnY; leftObstacles.push(newObstacle); leftObstacleSpawnTime += Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness; } if (LK.ticks >= rightObstacleSpawnTime) { var newObstacle = game.addChildAt(new Obstacle(), 0); newObstacle.x = 2048; newObstacle.y = -newObstacle.height; rightObstacles.push(newObstacle); rightObstacleSpawnTime += Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness; } if (bird.intersects(leftWall) && bird.xSpeed < 0 || bird.intersects(rightWall) && bird.xSpeed > 0) { bird.xSpeed = -bird.xSpeed; bird.flip(); game.score++; LK.setScore(game.score); LK.getSound('bounce').play(); } for (var i = leftObstacles.length - 1; i >= 0; i--) { leftObstacles[i]._move_migrated(game.obstacleSpeed); if (leftObstacles[i].y > 3232) { leftObstacles[i].destroy(); leftObstacles.splice(i, 1); } } for (var i = rightObstacles.length - 1; i >= 0; i--) { rightObstacles[i]._move_migrated(game.obstacleSpeed); if (rightObstacles[i].y > 3232) { rightObstacles[i].destroy(); rightObstacles.splice(i, 1); } } game.checkObstacleCollision(leftObstacles); game.checkObstacleCollision(rightObstacles); // --- Powerup logic start --- if (!game.powerups) game.powerups = []; if (typeof game.nextPowerupTick === "undefined") { game.nextPowerupTick = LK.ticks + 180 + Math.floor(Math.random() * 180); } if (LK.ticks >= game.nextPowerupTick) { var powerup = game.addChildAt(new Powerup(), 0); // Random X between 300 and 1748 (avoid walls) powerup.x = 300 + Math.random() * (2048 - 600); powerup.y = -100; game.powerups.push(powerup); // Next spawn in 3-6 seconds game.nextPowerupTick = LK.ticks + 180 + Math.floor(Math.random() * 180); } // Update powerups for (var i = game.powerups.length - 1; i >= 0; i--) { if (game.powerups[i] && typeof game.powerups[i].update === "function") { game.powerups[i].update(); } } // Powerup effect timers if (typeof game.powerupTimers === "undefined") game.powerupTimers = {}; // Check for bird-powerup collision for (var i = game.powerups.length - 1; i >= 0; i--) { var p = game.powerups[i]; if (bird.intersects(p)) { // Activate effect if (p.type === 'speed') { // Double speed for 3 seconds if (!game.powerupTimers.speed || LK.ticks > game.powerupTimers.speed) { bird.xSpeed *= 2; } game.powerupTimers.speed = LK.ticks + 180; } else if (p.type === 'immune') { // Immunity for 3 seconds game.powerupTimers.immune = LK.ticks + 180; } // Remove powerup p.destroy(); game.powerups.splice(i, 1); } } // Handle powerup expiration if (game.powerupTimers.speed && LK.ticks > game.powerupTimers.speed) { if (bird.xSpeed > 0) bird.xSpeed = 10.9375;else bird.xSpeed = -10.9375; delete game.powerupTimers.speed; } if (game.powerupTimers.immune && LK.ticks > game.powerupTimers.immune) { delete game.powerupTimers.immune; } // --- Powerup logic end --- // Update eggs if (game.eggs) { for (var i = game.eggs.length - 1; i >= 0; i--) { if (game.eggs[i] && typeof game.eggs[i].update === "function") { game.eggs[i].update(); } } } if (bird.y < 0 || bird.y > 2732) { LK.setScore(game.score); LK.getSound('gameOverJingle').play(); LK.showGameOver(); } };
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.xSpeed = 10.9375;
self.ySpeed = -20;
self.gravity = 1;
self.lift = -15;
self.flap = function () {
self.ySpeed = self.lift * 1.5;
LK.getSound('flap').play();
};
self._update_migrated = function () {
if (game.isMouseDown) {
self.ySpeed += self.gravity / 3;
} else {
self.ySpeed += self.gravity;
}
self.y += self.ySpeed;
self.x += self.xSpeed;
if (self.y <= 0 || self.y >= 2732) {
self.speed = -self.speed;
}
var targetRotation = Math.atan2(self.ySpeed, self.xSpeed * self.scale.x) / 2;
birdGraphics.rotation += (targetRotation - birdGraphics.rotation) / 10;
};
self.flip = function () {
self.scale.x *= -1;
};
});
// Egg class
var Egg = Container.expand(function () {
var self = Container.call(this);
var eggGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.ySpeed = 8;
self.update = function () {
self.y += self.ySpeed;
// Remove egg if it falls out of screen
if (self.y > 2800) {
self.destroy();
if (game.eggs) {
var idx = game.eggs.indexOf(self);
if (idx !== -1) game.eggs.splice(idx, 1);
}
}
};
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleShadow = self.attachAsset('obstacleShadow', {
anchorX: 0.5,
anchorY: 0.5
});
obstacleShadow.rotation = Math.PI / 4;
var obstacleShadow2 = self.attachAsset('obstacleShadow2', {
anchorX: 0.5,
anchorY: 0.5
});
obstacleShadow2.rotation = Math.PI / 4;
obstacleShadow2.y = -7;
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
obstacleGraphics.rotation = Math.PI / 4;
self.speed = 5;
self._move_migrated = function (speed) {
self.y += speed;
};
});
// Powerup class for floating special abilities
var Powerup = Container.expand(function () {
var self = Container.call(this);
// Randomly pick a type
var types = ['speed', 'immune'];
self.type = types[Math.floor(Math.random() * types.length)];
// Use different color for each type
var color = self.type === 'speed' ? 0xffd700 : 0x00ffcc;
var powerupGraphics = self.attachAsset('obstacleShadow', {
anchorX: 0.5,
anchorY: 0.5
});
powerupGraphics.tint = color;
powerupGraphics.scale.x = 0.7;
powerupGraphics.scale.y = 0.7;
// Add a text label for the type
var label = new Text2(self.type === 'speed' ? 'S' : 'I', {
size: 120,
fill: '#222a9a',
font: 'Impact',
align: 'center'
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.speed = 5;
self.update = function () {
self.y += self.speed;
// Remove if out of screen
if (self.y > 2900) {
self.destroy();
if (game.powerups) {
var idx = game.powerups.indexOf(self);
if (idx !== -1) game.powerups.splice(idx, 1);
}
}
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var tutorialTextWhite = new Text2('Tap to Flap\nHold to Float', {
size: 150,
fill: '#ffffff',
font: 'Impact',
align: 'center'
});
tutorialTextWhite.anchor.set(.5, 1);
tutorialTextWhite.x = -4;
tutorialTextWhite.y = -62;
LK.gui.bottom.addChild(tutorialTextWhite);
var tutorialText = new Text2('Tap to Flap\nHold to Float', {
size: 150,
fill: '#3a84f7',
font: 'Impact',
dropShadow: true,
dropShadowColor: '#222a9a',
dropShadowBlur: 5,
dropShadowDistance: 7,
dropShadowAngle: 0,
align: 'center'
});
tutorialText.anchor.set(.5, 1);
tutorialText.y = -50;
LK.gui.bottom.addChild(tutorialText);
game.score = 0;
game.obstacleSpeed = 5;
game.obstacleSpeedIncrease = 0.005;
game.checkObstacleCollision = function (obstacles) {
for (var i = 0; i < obstacles.length; i++) {
obstacles[i]._move_migrated();
var dist = Math.sqrt(Math.pow(bird.x - obstacles[i].x, 2) + Math.pow(bird.y - obstacles[i].y, 2));
if (dist < 280) {
// If immune, skip game over
if (game.powerupTimers && game.powerupTimers.immune && LK.ticks <= game.powerupTimers.immune) {
continue;
}
LK.setScore(game.score);
LK.getSound('gameOverJingle').play();
LK.showGameOver();
}
}
};
game.setBackgroundColor(0xadd8e6);
var scoreText = new Text2('0', {
size: 150,
fill: '#3a84f7',
font: 'Impact',
dropShadow: true,
dropShadowColor: '#222a9a',
dropShadowBlur: 5,
dropShadowDistance: 7,
dropShadowAngle: 0
});
scoreText.anchor.set(.5, 0);
LK.gui.top.addChild(scoreText);
var scoreText2 = new Text2('0', {
size: 150,
fill: '#ffffff',
font: 'Impact'
});
scoreText2.anchor.set(.5, 0);
scoreText2.x = -4;
scoreText2.y = -5;
LK.gui.top.addChild(scoreText2);
LK.gui.top.addChild(scoreText);
var bird = game.addChild(new Bird());
var leftWall = game.addChild(new Wall());
leftWall.x = 0;
leftWall.y = 1366;
var rightWall = game.addChild(new Wall());
rightWall.x = 2048;
rightWall.y = 1366;
var leftObstacles = [],
rightObstacles = [];
var obstacleSpawnRandomness = 120;
var obstacleSpawnRandomnessDecrease = 0.025 * (2 / 3);
var obstacleSpawnY = -500;
var leftObstacleSpawnTime = Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness;
var rightObstacleSpawnTime = Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness;
bird.x = 1024;
bird.y = 1366;
game.isMouseDown = false;
game.down = function (x, y, obj) {
bird.flap();
game.isMouseDown = true;
// Lay an egg at bird's position
if (!game.eggs) game.eggs = [];
var egg = game.addChild(new Egg());
egg.x = bird.x;
egg.y = bird.y + 80;
egg.scale.x = 8;
egg.scale.y = 8;
game.eggs.push(egg);
};
game.up = function (x, y, obj) {
game.isMouseDown = false;
};
game.update = function () {
bird._update_migrated();
if (game.score > 2) {
tutorialText.y += 5;
tutorialTextWhite.y += 5;
}
scoreText.setText(game.score);
scoreText2.setText(game.score);
game.obstacleSpeed += game.obstacleSpeedIncrease;
obstacleSpawnRandomness -= obstacleSpawnRandomnessDecrease;
if (obstacleSpawnRandomness < 20) {
obstacleSpawnRandomness = 20;
}
if (LK.ticks >= leftObstacleSpawnTime) {
var newObstacle = game.addChildAt(new Obstacle(), 0);
newObstacle.x = 0;
newObstacle.y = obstacleSpawnY;
leftObstacles.push(newObstacle);
leftObstacleSpawnTime += Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness;
}
if (LK.ticks >= rightObstacleSpawnTime) {
var newObstacle = game.addChildAt(new Obstacle(), 0);
newObstacle.x = 2048;
newObstacle.y = -newObstacle.height;
rightObstacles.push(newObstacle);
rightObstacleSpawnTime += Math.floor(Math.random() * obstacleSpawnRandomness) + obstacleSpawnRandomness;
}
if (bird.intersects(leftWall) && bird.xSpeed < 0 || bird.intersects(rightWall) && bird.xSpeed > 0) {
bird.xSpeed = -bird.xSpeed;
bird.flip();
game.score++;
LK.setScore(game.score);
LK.getSound('bounce').play();
}
for (var i = leftObstacles.length - 1; i >= 0; i--) {
leftObstacles[i]._move_migrated(game.obstacleSpeed);
if (leftObstacles[i].y > 3232) {
leftObstacles[i].destroy();
leftObstacles.splice(i, 1);
}
}
for (var i = rightObstacles.length - 1; i >= 0; i--) {
rightObstacles[i]._move_migrated(game.obstacleSpeed);
if (rightObstacles[i].y > 3232) {
rightObstacles[i].destroy();
rightObstacles.splice(i, 1);
}
}
game.checkObstacleCollision(leftObstacles);
game.checkObstacleCollision(rightObstacles);
// --- Powerup logic start ---
if (!game.powerups) game.powerups = [];
if (typeof game.nextPowerupTick === "undefined") {
game.nextPowerupTick = LK.ticks + 180 + Math.floor(Math.random() * 180);
}
if (LK.ticks >= game.nextPowerupTick) {
var powerup = game.addChildAt(new Powerup(), 0);
// Random X between 300 and 1748 (avoid walls)
powerup.x = 300 + Math.random() * (2048 - 600);
powerup.y = -100;
game.powerups.push(powerup);
// Next spawn in 3-6 seconds
game.nextPowerupTick = LK.ticks + 180 + Math.floor(Math.random() * 180);
}
// Update powerups
for (var i = game.powerups.length - 1; i >= 0; i--) {
if (game.powerups[i] && typeof game.powerups[i].update === "function") {
game.powerups[i].update();
}
}
// Powerup effect timers
if (typeof game.powerupTimers === "undefined") game.powerupTimers = {};
// Check for bird-powerup collision
for (var i = game.powerups.length - 1; i >= 0; i--) {
var p = game.powerups[i];
if (bird.intersects(p)) {
// Activate effect
if (p.type === 'speed') {
// Double speed for 3 seconds
if (!game.powerupTimers.speed || LK.ticks > game.powerupTimers.speed) {
bird.xSpeed *= 2;
}
game.powerupTimers.speed = LK.ticks + 180;
} else if (p.type === 'immune') {
// Immunity for 3 seconds
game.powerupTimers.immune = LK.ticks + 180;
}
// Remove powerup
p.destroy();
game.powerups.splice(i, 1);
}
}
// Handle powerup expiration
if (game.powerupTimers.speed && LK.ticks > game.powerupTimers.speed) {
if (bird.xSpeed > 0) bird.xSpeed = 10.9375;else bird.xSpeed = -10.9375;
delete game.powerupTimers.speed;
}
if (game.powerupTimers.immune && LK.ticks > game.powerupTimers.immune) {
delete game.powerupTimers.immune;
}
// --- Powerup logic end ---
// Update eggs
if (game.eggs) {
for (var i = game.eggs.length - 1; i >= 0; i--) {
if (game.eggs[i] && typeof game.eggs[i].update === "function") {
game.eggs[i].update();
}
}
}
if (bird.y < 0 || bird.y > 2732) {
LK.setScore(game.score);
LK.getSound('gameOverJingle').play();
LK.showGameOver();
}
};