/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * 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; }; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; self.speed = 3; // Start rotation animation tween(coinGraphics, { rotation: Math.PI * 2 }, { duration: 2000, easing: tween.linear, onFinish: function onFinish() { if (!self.collected) { tween(coinGraphics, { rotation: Math.PI * 4 }, { duration: 2000, easing: tween.linear, onFinish: arguments.callee }); } } }); self._move_migrated = function (speed) { self.y += speed; }; self.collect = function () { if (!self.collected) { self.collected = true; LK.getSound('coinCollect').play(); tween(self, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); } }; return self; }); var Leaderboard = Container.expand(function () { var self = Container.call(this); // Leaderboard background var leaderBg = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 1 }); leaderBg.alpha = 0.9; leaderBg.tint = 0x2196F3; // Title var titleText = new Text2('LEADERBOARD', { size: 150, fill: '#ffffff', font: 'Arial Black', align: 'center' }); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -500; self.addChild(titleText); // Get high scores from storage var highScores = storage.highScores || [0, 0, 0, 0, 0]; // Display top 5 scores for (var i = 0; i < 5; i++) { var scoreText = new Text2(i + 1 + '. ' + highScores[i], { size: 100, fill: '#ffd700', font: 'Arial Black', align: 'center' }); scoreText.anchor.set(0.5, 0.5); scoreText.x = 0; scoreText.y = -300 + i * 120; self.addChild(scoreText); } // Back button var backButton = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1 }); backButton.tint = 0xFF5722; backButton.y = 400; var backText = new Text2('BACK', { size: 120, fill: '#ffffff', font: 'Arial Black', align: 'center' }); backText.anchor.set(0.5, 0.5); backText.x = 0; backText.y = 400; self.addChild(backText); self.down = function (x, y, obj) { // Use the x, y coordinates directly instead of trying to convert from obj // Check back button click (button is at y=400, height is about 100) if (y > 350 && y < 450) { game.showMenu(); } }; return self; }); var Menu = Container.expand(function () { var self = Container.call(this); // Menu background var menuBg = self.attachAsset('wall', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 1 }); menuBg.alpha = 0.8; menuBg.tint = 0x87CEEB; // Title var titleText = new Text2('FLAPPY BIRD', { size: 200, fill: '#ff6b35', font: 'Arial Black', dropShadow: true, dropShadowColor: '#b8860b', dropShadowBlur: 10, dropShadowDistance: 5, align: 'center' }); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -400; self.addChild(titleText); // Play button var playButton = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1 }); playButton.tint = 0x4CAF50; playButton.y = -100; var playText = new Text2('PLAY', { size: 120, fill: '#ffffff', font: 'Arial Black', align: 'center' }); playText.anchor.set(0.5, 0.5); playText.x = 0; playText.y = -100; self.addChild(playText); // Leaderboard button var leaderButton = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1 }); leaderButton.tint = 0x2196F3; leaderButton.y = 100; var leaderText = new Text2('LEADERBOARD', { size: 100, fill: '#ffffff', font: 'Arial Black', align: 'center' }); leaderText.anchor.set(0.5, 0.5); leaderText.x = 0; leaderText.y = 100; self.addChild(leaderText); // Best score display var bestScore = storage.bestScore || 0; var bestScoreText = new Text2('Best Score: ' + bestScore, { size: 80, fill: '#ffd700', font: 'Arial Black', align: 'center' }); bestScoreText.anchor.set(0.5, 0.5); bestScoreText.x = 0; bestScoreText.y = 300; self.addChild(bestScoreText); self.down = function (x, y, obj) { // Use the x, y coordinates directly instead of trying to convert from obj // Check play button click (button is at y=-100, height is about 100) if (y > -150 && y < -50) { game.startGame(); } // Check leaderboard button click (button is at y=100, height is about 100) if (y > 50 && y < 150) { game.showLeaderboard(); } }; return self; }); 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; }; }); 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: 'Arial Black', 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: '#ff6b35', font: 'Arial Black', dropShadow: true, dropShadowColor: '#b8860b', dropShadowBlur: 8, dropShadowDistance: 4, dropShadowAngle: 0, align: 'center' }); tutorialText.anchor.set(.5, 1); tutorialText.y = -50; LK.gui.bottom.addChild(tutorialText); game.score = 0; game.coinsCollected = 0; game.lives = 1; game.obstacleSpeed = 5; game.obstacleSpeedIncrease = 0.005; game.gameState = 'menu'; // 'menu', 'playing', 'leaderboard' game.menu = null; game.leaderboard = null; 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) { game.lives--; livesText.setText('Lives: ' + game.lives); livesText2.setText('Lives: ' + game.lives); if (game.lives <= 0) { game.saveScore(); LK.setScore(game.score); LK.getSound('gameOverJingle').play(); LK.showGameOver(); } else { // Flash red to indicate life lost LK.effects.flashScreen(0xff0000, 500); // Reset bird position bird.x = 1024; bird.y = 1366; bird.ySpeed = 0; } } } }; game.saveScore = function () { // Update best score var bestScore = storage.bestScore || 0; if (game.score > bestScore) { storage.bestScore = game.score; } // Update high scores list var highScores = storage.highScores || [0, 0, 0, 0, 0]; highScores.push(game.score); highScores.sort(function (a, b) { return b - a; }); highScores = highScores.slice(0, 5); storage.highScores = highScores; }; game.showMenu = function () { game.gameState = 'menu'; if (game.leaderboard) { game.leaderboard.destroy(); game.leaderboard = null; } if (!game.menu) { game.menu = game.addChild(new Menu()); game.menu.x = 1024; game.menu.y = 1366; } // Hide game UI elements tutorialText.visible = false; tutorialTextWhite.visible = false; scoreText.visible = false; scoreText2.visible = false; coinText.visible = false; coinText2.visible = false; livesText.visible = false; livesText2.visible = false; // Hide game objects bird.visible = false; leftWall.visible = false; rightWall.visible = false; }; game.showLeaderboard = function () { game.gameState = 'leaderboard'; if (game.menu) { game.menu.destroy(); game.menu = null; } if (!game.leaderboard) { game.leaderboard = game.addChild(new Leaderboard()); game.leaderboard.x = 1024; game.leaderboard.y = 1366; } }; game.startGame = function () { game.gameState = 'playing'; if (game.menu) { game.menu.destroy(); game.menu = null; } if (game.leaderboard) { game.leaderboard.destroy(); game.leaderboard = null; } // Reset game state game.score = 0; game.coinsCollected = 0; game.lives = 1; game.obstacleSpeed = 5; // Show game UI elements tutorialText.visible = true; tutorialTextWhite.visible = true; scoreText.visible = true; scoreText2.visible = true; coinText.visible = true; coinText2.visible = true; livesText.visible = true; livesText2.visible = true; // Show and reset game objects bird.visible = true; bird.x = 1024; bird.y = 1366; bird.ySpeed = 0; leftWall.visible = true; rightWall.visible = true; // Clear obstacles and coins for (var i = leftObstacles.length - 1; i >= 0; i--) { leftObstacles[i].destroy(); leftObstacles.splice(i, 1); } for (var i = rightObstacles.length - 1; i >= 0; i--) { rightObstacles[i].destroy(); rightObstacles.splice(i, 1); } for (var i = coins.length - 1; i >= 0; i--) { coins[i].destroy(); coins.splice(i, 1); } // Update UI scoreText.setText('0'); scoreText2.setText('0'); coinText.setText('Coins: 0'); coinText2.setText('Coins: 0'); livesText.setText('Lives: 1'); livesText2.setText('Lives: 1'); }; game.setBackgroundColor(0x87CEEB); var scoreText = new Text2('0', { size: 150, fill: '#ff6b35', font: 'Arial Black', dropShadow: true, dropShadowColor: '#b8860b', dropShadowBlur: 8, dropShadowDistance: 4, dropShadowAngle: 0 }); scoreText.anchor.set(.5, 0); LK.gui.top.addChild(scoreText); var scoreText2 = new Text2('0', { size: 150, fill: '#ffffff', font: 'Arial Black' }); scoreText2.anchor.set(.5, 0); scoreText2.x = -4; scoreText2.y = -5; LK.gui.top.addChild(scoreText2); LK.gui.top.addChild(scoreText); var coinText = new Text2('Coins: 0', { size: 80, fill: '#ffd700', font: 'Arial Black', dropShadow: true, dropShadowColor: '#b8860b', dropShadowBlur: 5, dropShadowDistance: 2, dropShadowAngle: 0 }); coinText.anchor.set(1, 0); coinText.x = -20; coinText.y = 20; LK.gui.topRight.addChild(coinText); var coinText2 = new Text2('Coins: 0', { size: 80, fill: '#ffffff', font: 'Arial Black' }); coinText2.anchor.set(1, 0); coinText2.x = -24; coinText2.y = 15; LK.gui.topRight.addChild(coinText2); LK.gui.topRight.addChild(coinText); var livesText = new Text2('Lives: 1', { size: 80, fill: '#ff4444', font: 'Arial Black', dropShadow: true, dropShadowColor: '#aa0000', dropShadowBlur: 5, dropShadowDistance: 2, dropShadowAngle: 0 }); livesText.anchor.set(1, 0); livesText.x = -20; livesText.y = 120; LK.gui.topRight.addChild(livesText); var livesText2 = new Text2('Lives: 1', { size: 80, fill: '#ffffff', font: 'Arial Black' }); livesText2.anchor.set(1, 0); livesText2.x = -24; livesText2.y = 115; LK.gui.topRight.addChild(livesText2); LK.gui.topRight.addChild(livesText); 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 = [], coins = []; var coinSpawnTime = 120; var coinSpawnCounter = 0; var obstacleSpawnRandomness = 180; 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; // Start with menu game.showMenu(); game.down = function (x, y, obj) { if (game.gameState === 'playing') { bird.flap(); game.isMouseDown = true; } }; game.up = function (x, y, obj) { if (game.gameState === 'playing') { game.isMouseDown = false; } }; game.update = function () { if (game.gameState !== 'playing') { return; } 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 < 40) { obstacleSpawnRandomness = 40; } 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); } } // Spawn coins coinSpawnCounter++; if (coinSpawnCounter >= coinSpawnTime) { var newCoin = game.addChild(new Coin()); newCoin.x = Math.random() * 1500 + 300; // Random X between walls newCoin.y = -100; coins.push(newCoin); coinSpawnCounter = 0; coinSpawnTime = Math.random() * 180 + 60; // Random spawn time } // Move and check coin collection for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; if (!coin.collected) { coin._move_migrated(game.obstacleSpeed); // Check collision with bird if (bird.intersects(coin)) { coin.collect(); game.coinsCollected++; game.score += 3; // Give bonus points for coins LK.setScore(game.score); scoreText.setText(game.score); scoreText2.setText(game.score); coinText.setText('Coins: ' + game.coinsCollected); coinText2.setText('Coins: ' + game.coinsCollected); // Check for extra life every 10 coins (maximum 3 lives) if (game.coinsCollected % 10 === 0 && game.lives < 3) { game.lives++; livesText.setText('Lives: ' + game.lives); livesText2.setText('Lives: ' + game.lives); // Flash the lives text to indicate extra life gained tween(livesText, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(livesText, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); } }); } coins.splice(i, 1); continue; } // Remove coins that are off screen if (coin.y > 3000) { coin.destroy(); coins.splice(i, 1); } } } game.checkObstacleCollision(leftObstacles); game.checkObstacleCollision(rightObstacles); if (bird.y < 0 || bird.y > 2732) { game.lives--; livesText.setText('Lives: ' + game.lives); livesText2.setText('Lives: ' + game.lives); if (game.lives <= 0) { game.saveScore(); LK.setScore(game.score); LK.getSound('gameOverJingle').play(); LK.showGameOver(); } else { // Flash red to indicate life lost LK.effects.flashScreen(0xff0000, 500); // Reset bird position bird.x = 1024; bird.y = 1366; bird.ySpeed = 0; } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* 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;
};
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.speed = 3;
// Start rotation animation
tween(coinGraphics, {
rotation: Math.PI * 2
}, {
duration: 2000,
easing: tween.linear,
onFinish: function onFinish() {
if (!self.collected) {
tween(coinGraphics, {
rotation: Math.PI * 4
}, {
duration: 2000,
easing: tween.linear,
onFinish: arguments.callee
});
}
}
});
self._move_migrated = function (speed) {
self.y += speed;
};
self.collect = function () {
if (!self.collected) {
self.collected = true;
LK.getSound('coinCollect').play();
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
}
};
return self;
});
var Leaderboard = Container.expand(function () {
var self = Container.call(this);
// Leaderboard background
var leaderBg = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 1
});
leaderBg.alpha = 0.9;
leaderBg.tint = 0x2196F3;
// Title
var titleText = new Text2('LEADERBOARD', {
size: 150,
fill: '#ffffff',
font: 'Arial Black',
align: 'center'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -500;
self.addChild(titleText);
// Get high scores from storage
var highScores = storage.highScores || [0, 0, 0, 0, 0];
// Display top 5 scores
for (var i = 0; i < 5; i++) {
var scoreText = new Text2(i + 1 + '. ' + highScores[i], {
size: 100,
fill: '#ffd700',
font: 'Arial Black',
align: 'center'
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 0;
scoreText.y = -300 + i * 120;
self.addChild(scoreText);
}
// Back button
var backButton = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
});
backButton.tint = 0xFF5722;
backButton.y = 400;
var backText = new Text2('BACK', {
size: 120,
fill: '#ffffff',
font: 'Arial Black',
align: 'center'
});
backText.anchor.set(0.5, 0.5);
backText.x = 0;
backText.y = 400;
self.addChild(backText);
self.down = function (x, y, obj) {
// Use the x, y coordinates directly instead of trying to convert from obj
// Check back button click (button is at y=400, height is about 100)
if (y > 350 && y < 450) {
game.showMenu();
}
};
return self;
});
var Menu = Container.expand(function () {
var self = Container.call(this);
// Menu background
var menuBg = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 1
});
menuBg.alpha = 0.8;
menuBg.tint = 0x87CEEB;
// Title
var titleText = new Text2('FLAPPY BIRD', {
size: 200,
fill: '#ff6b35',
font: 'Arial Black',
dropShadow: true,
dropShadowColor: '#b8860b',
dropShadowBlur: 10,
dropShadowDistance: 5,
align: 'center'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -400;
self.addChild(titleText);
// Play button
var playButton = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
});
playButton.tint = 0x4CAF50;
playButton.y = -100;
var playText = new Text2('PLAY', {
size: 120,
fill: '#ffffff',
font: 'Arial Black',
align: 'center'
});
playText.anchor.set(0.5, 0.5);
playText.x = 0;
playText.y = -100;
self.addChild(playText);
// Leaderboard button
var leaderButton = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
});
leaderButton.tint = 0x2196F3;
leaderButton.y = 100;
var leaderText = new Text2('LEADERBOARD', {
size: 100,
fill: '#ffffff',
font: 'Arial Black',
align: 'center'
});
leaderText.anchor.set(0.5, 0.5);
leaderText.x = 0;
leaderText.y = 100;
self.addChild(leaderText);
// Best score display
var bestScore = storage.bestScore || 0;
var bestScoreText = new Text2('Best Score: ' + bestScore, {
size: 80,
fill: '#ffd700',
font: 'Arial Black',
align: 'center'
});
bestScoreText.anchor.set(0.5, 0.5);
bestScoreText.x = 0;
bestScoreText.y = 300;
self.addChild(bestScoreText);
self.down = function (x, y, obj) {
// Use the x, y coordinates directly instead of trying to convert from obj
// Check play button click (button is at y=-100, height is about 100)
if (y > -150 && y < -50) {
game.startGame();
}
// Check leaderboard button click (button is at y=100, height is about 100)
if (y > 50 && y < 150) {
game.showLeaderboard();
}
};
return self;
});
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;
};
});
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: 'Arial Black',
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: '#ff6b35',
font: 'Arial Black',
dropShadow: true,
dropShadowColor: '#b8860b',
dropShadowBlur: 8,
dropShadowDistance: 4,
dropShadowAngle: 0,
align: 'center'
});
tutorialText.anchor.set(.5, 1);
tutorialText.y = -50;
LK.gui.bottom.addChild(tutorialText);
game.score = 0;
game.coinsCollected = 0;
game.lives = 1;
game.obstacleSpeed = 5;
game.obstacleSpeedIncrease = 0.005;
game.gameState = 'menu'; // 'menu', 'playing', 'leaderboard'
game.menu = null;
game.leaderboard = null;
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) {
game.lives--;
livesText.setText('Lives: ' + game.lives);
livesText2.setText('Lives: ' + game.lives);
if (game.lives <= 0) {
game.saveScore();
LK.setScore(game.score);
LK.getSound('gameOverJingle').play();
LK.showGameOver();
} else {
// Flash red to indicate life lost
LK.effects.flashScreen(0xff0000, 500);
// Reset bird position
bird.x = 1024;
bird.y = 1366;
bird.ySpeed = 0;
}
}
}
};
game.saveScore = function () {
// Update best score
var bestScore = storage.bestScore || 0;
if (game.score > bestScore) {
storage.bestScore = game.score;
}
// Update high scores list
var highScores = storage.highScores || [0, 0, 0, 0, 0];
highScores.push(game.score);
highScores.sort(function (a, b) {
return b - a;
});
highScores = highScores.slice(0, 5);
storage.highScores = highScores;
};
game.showMenu = function () {
game.gameState = 'menu';
if (game.leaderboard) {
game.leaderboard.destroy();
game.leaderboard = null;
}
if (!game.menu) {
game.menu = game.addChild(new Menu());
game.menu.x = 1024;
game.menu.y = 1366;
}
// Hide game UI elements
tutorialText.visible = false;
tutorialTextWhite.visible = false;
scoreText.visible = false;
scoreText2.visible = false;
coinText.visible = false;
coinText2.visible = false;
livesText.visible = false;
livesText2.visible = false;
// Hide game objects
bird.visible = false;
leftWall.visible = false;
rightWall.visible = false;
};
game.showLeaderboard = function () {
game.gameState = 'leaderboard';
if (game.menu) {
game.menu.destroy();
game.menu = null;
}
if (!game.leaderboard) {
game.leaderboard = game.addChild(new Leaderboard());
game.leaderboard.x = 1024;
game.leaderboard.y = 1366;
}
};
game.startGame = function () {
game.gameState = 'playing';
if (game.menu) {
game.menu.destroy();
game.menu = null;
}
if (game.leaderboard) {
game.leaderboard.destroy();
game.leaderboard = null;
}
// Reset game state
game.score = 0;
game.coinsCollected = 0;
game.lives = 1;
game.obstacleSpeed = 5;
// Show game UI elements
tutorialText.visible = true;
tutorialTextWhite.visible = true;
scoreText.visible = true;
scoreText2.visible = true;
coinText.visible = true;
coinText2.visible = true;
livesText.visible = true;
livesText2.visible = true;
// Show and reset game objects
bird.visible = true;
bird.x = 1024;
bird.y = 1366;
bird.ySpeed = 0;
leftWall.visible = true;
rightWall.visible = true;
// Clear obstacles and coins
for (var i = leftObstacles.length - 1; i >= 0; i--) {
leftObstacles[i].destroy();
leftObstacles.splice(i, 1);
}
for (var i = rightObstacles.length - 1; i >= 0; i--) {
rightObstacles[i].destroy();
rightObstacles.splice(i, 1);
}
for (var i = coins.length - 1; i >= 0; i--) {
coins[i].destroy();
coins.splice(i, 1);
}
// Update UI
scoreText.setText('0');
scoreText2.setText('0');
coinText.setText('Coins: 0');
coinText2.setText('Coins: 0');
livesText.setText('Lives: 1');
livesText2.setText('Lives: 1');
};
game.setBackgroundColor(0x87CEEB);
var scoreText = new Text2('0', {
size: 150,
fill: '#ff6b35',
font: 'Arial Black',
dropShadow: true,
dropShadowColor: '#b8860b',
dropShadowBlur: 8,
dropShadowDistance: 4,
dropShadowAngle: 0
});
scoreText.anchor.set(.5, 0);
LK.gui.top.addChild(scoreText);
var scoreText2 = new Text2('0', {
size: 150,
fill: '#ffffff',
font: 'Arial Black'
});
scoreText2.anchor.set(.5, 0);
scoreText2.x = -4;
scoreText2.y = -5;
LK.gui.top.addChild(scoreText2);
LK.gui.top.addChild(scoreText);
var coinText = new Text2('Coins: 0', {
size: 80,
fill: '#ffd700',
font: 'Arial Black',
dropShadow: true,
dropShadowColor: '#b8860b',
dropShadowBlur: 5,
dropShadowDistance: 2,
dropShadowAngle: 0
});
coinText.anchor.set(1, 0);
coinText.x = -20;
coinText.y = 20;
LK.gui.topRight.addChild(coinText);
var coinText2 = new Text2('Coins: 0', {
size: 80,
fill: '#ffffff',
font: 'Arial Black'
});
coinText2.anchor.set(1, 0);
coinText2.x = -24;
coinText2.y = 15;
LK.gui.topRight.addChild(coinText2);
LK.gui.topRight.addChild(coinText);
var livesText = new Text2('Lives: 1', {
size: 80,
fill: '#ff4444',
font: 'Arial Black',
dropShadow: true,
dropShadowColor: '#aa0000',
dropShadowBlur: 5,
dropShadowDistance: 2,
dropShadowAngle: 0
});
livesText.anchor.set(1, 0);
livesText.x = -20;
livesText.y = 120;
LK.gui.topRight.addChild(livesText);
var livesText2 = new Text2('Lives: 1', {
size: 80,
fill: '#ffffff',
font: 'Arial Black'
});
livesText2.anchor.set(1, 0);
livesText2.x = -24;
livesText2.y = 115;
LK.gui.topRight.addChild(livesText2);
LK.gui.topRight.addChild(livesText);
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 = [],
coins = [];
var coinSpawnTime = 120;
var coinSpawnCounter = 0;
var obstacleSpawnRandomness = 180;
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;
// Start with menu
game.showMenu();
game.down = function (x, y, obj) {
if (game.gameState === 'playing') {
bird.flap();
game.isMouseDown = true;
}
};
game.up = function (x, y, obj) {
if (game.gameState === 'playing') {
game.isMouseDown = false;
}
};
game.update = function () {
if (game.gameState !== 'playing') {
return;
}
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 < 40) {
obstacleSpawnRandomness = 40;
}
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);
}
}
// Spawn coins
coinSpawnCounter++;
if (coinSpawnCounter >= coinSpawnTime) {
var newCoin = game.addChild(new Coin());
newCoin.x = Math.random() * 1500 + 300; // Random X between walls
newCoin.y = -100;
coins.push(newCoin);
coinSpawnCounter = 0;
coinSpawnTime = Math.random() * 180 + 60; // Random spawn time
}
// Move and check coin collection
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (!coin.collected) {
coin._move_migrated(game.obstacleSpeed);
// Check collision with bird
if (bird.intersects(coin)) {
coin.collect();
game.coinsCollected++;
game.score += 3; // Give bonus points for coins
LK.setScore(game.score);
scoreText.setText(game.score);
scoreText2.setText(game.score);
coinText.setText('Coins: ' + game.coinsCollected);
coinText2.setText('Coins: ' + game.coinsCollected);
// Check for extra life every 10 coins (maximum 3 lives)
if (game.coinsCollected % 10 === 0 && game.lives < 3) {
game.lives++;
livesText.setText('Lives: ' + game.lives);
livesText2.setText('Lives: ' + game.lives);
// Flash the lives text to indicate extra life gained
tween(livesText, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(livesText, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
});
}
coins.splice(i, 1);
continue;
}
// Remove coins that are off screen
if (coin.y > 3000) {
coin.destroy();
coins.splice(i, 1);
}
}
}
game.checkObstacleCollision(leftObstacles);
game.checkObstacleCollision(rightObstacles);
if (bird.y < 0 || bird.y > 2732) {
game.lives--;
livesText.setText('Lives: ' + game.lives);
livesText2.setText('Lives: ' + game.lives);
if (game.lives <= 0) {
game.saveScore();
LK.setScore(game.score);
LK.getSound('gameOverJingle').play();
LK.showGameOver();
} else {
// Flash red to indicate life lost
LK.effects.flashScreen(0xff0000, 500);
// Reset bird position
bird.x = 1024;
bird.y = 1366;
bird.ySpeed = 0;
}
}
};