/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
gamesPlayed: 0,
globalScores: []
});
/****
* Classes
****/
var Airplane = Container.expand(function () {
var self = Container.call(this);
var airplaneGraphics = self.attachAsset('airplane', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
self.velocity = 0;
self.gravity = 0.6;
self.jumpPower = -10;
self.maxVelocity = 12;
self.update = function () {
// Apply gravity
self.velocity += self.gravity;
// Limit velocity
if (self.velocity > self.maxVelocity) {
self.velocity = self.maxVelocity;
}
if (self.velocity < -self.maxVelocity) {
self.velocity = -self.maxVelocity;
}
// Update position
self.y += self.velocity;
// Rotate airplane based on velocity for visual effect
airplaneGraphics.rotation = Math.max(-0.5, Math.min(0.5, self.velocity * 0.05));
// Allow airplane to go off screen (will be caught by game over logic)
};
self.jump = function () {
self.velocity = self.jumpPower;
LK.getSound('fly').play();
};
return self;
});
var Building = Container.expand(function (topHeight, bottomHeight, gapY) {
var self = Container.call(this);
var gapSize = 320;
// Top building
var topBuilding = self.attachAsset('building', {
anchorX: 0,
anchorY: 1,
scaleY: (gapY - gapSize / 2) / 100,
rotation: 0 // Revert the rotation of the top building to its original orientation
});
topBuilding.y = gapY - gapSize / 2; // Position top building at gap start
// Bottom building
var bottomBuilding = self.attachAsset('building', {
anchorX: 0,
anchorY: 0,
scaleY: (2732 - (gapY + gapSize / 2)) / 100
});
bottomBuilding.y = gapY + gapSize / 2; // Position bottom building at gap end
self.speed = -4;
self.passed = false;
self.update = function () {
self.x += self.speed;
};
self.checkCollision = function (airplane) {
// Get airplane's actual scaled dimensions with reduced hitbox for better gameplay
var airplaneScaledWidth = 120 * 2.2 * 0.7; // Reduce hitbox by 30%
var airplaneScaledHeight = 60 * 2.2 * 0.7; // Reduce hitbox by 30%
var airplaneLeft = airplane.x - airplaneScaledWidth / 2;
var airplaneRight = airplane.x + airplaneScaledWidth / 2;
var airplaneTop = airplane.y - airplaneScaledHeight / 2;
var airplaneBottom = airplane.y + airplaneScaledHeight / 2;
// Get building dimensions (no scaling applied to buildings, so use original width)
var buildingWidth = 175;
var buildingLeft = self.x + 10; // Add small margin to building hitbox
var buildingRight = self.x + buildingWidth - 10; // Reduce building hitbox width
// Check if airplane is within building's x range
if (airplaneRight > buildingLeft && airplaneLeft < buildingRight) {
// Check collision with top building (add small margin)
if (airplaneTop < topBuilding.y - 5) {
return true;
}
// Check collision with bottom building (add small margin)
if (airplaneBottom > bottomBuilding.y + 5) {
return true;
}
}
return false;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.update = function () {
self.x += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB,
scale: 2.0 // Reduce the scale to make the screen appear smaller
});
/****
* Game Code
****/
// Add sea background
var seaBg = game.addChild(LK.getAsset('seaBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Add fish shadows in the sea
var fishShadows = [];
for (var i = 0; i < 12; i++) {
var shadowType = 'fishShadow' + (Math.floor(Math.random() * 3) + 1);
var fishShadow = game.addChild(LK.getAsset(shadowType, {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2200,
y: 1200 + Math.random() * 1000,
alpha: 0.15 + Math.random() * 0.25,
scaleX: 0.8 + Math.random() * 0.4,
scaleY: 0.8 + Math.random() * 0.4
}));
fishShadow.speedX = -0.5 - Math.random() * 1.5;
fishShadow.speedY = (Math.random() - 0.5) * 0.3;
fishShadow.originalX = fishShadow.x;
fishShadow.originalY = fishShadow.y;
fishShadows.push(fishShadow);
}
// Add clouds in the sky
var clouds = [];
for (var i = 0; i < 6; i++) {
var cloud = game.addChild(LK.getAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2400,
y: 200 + Math.random() * 400,
alpha: 0.6 + Math.random() * 0.3,
scaleX: 1.2 + Math.random() * 0.8,
scaleY: 0.8 + Math.random() * 0.6
}));
cloud.speedX = -0.2 - Math.random() * 0.3;
clouds.push(cloud);
}
// Game variables
var airplane;
var buildings = [];
var gameSpeed = 4;
var buildingSpawnTimer = 0;
var buildingSpawnInterval = 220; // frames between buildings
var gameStarted = false;
var lastTapTime = 0;
var tapCooldown = 50; // milliseconds between taps (20 taps per second max)
// Menu state variables
var gameState = 'menu'; // 'menu', 'playing', 'leaderboard'
var menuButtons = [];
// UI Elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Menu UI elements
var titleTxt = new Text2('9/11', {
size: 120,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 1024;
titleTxt.y = 800;
game.addChild(titleTxt);
var playBtn = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 1024;
playBtn.y = 1200;
game.addChild(playBtn);
var leaderboardBtn = new Text2('LEADERBOARD', {
size: 60,
fill: 0x0080FF
});
leaderboardBtn.anchor.set(0.5, 0.5);
leaderboardBtn.x = 1024;
leaderboardBtn.y = 1350;
game.addChild(leaderboardBtn);
var highScoreTxt = new Text2('HIGH SCORE: ' + storage.highScore, {
size: 60,
fill: 0xFFD700
});
highScoreTxt.anchor.set(0.5, 0.5);
highScoreTxt.x = 1024;
highScoreTxt.y = 1050;
game.addChild(highScoreTxt);
// Leaderboard UI elements (initially hidden)
var leaderboardTitleTxt = new Text2('LEADERBOARD', {
size: 100,
fill: 0xFFFFFF
});
leaderboardTitleTxt.anchor.set(0.5, 0.5);
leaderboardTitleTxt.x = 1024;
leaderboardTitleTxt.y = 600;
leaderboardTitleTxt.visible = false;
game.addChild(leaderboardTitleTxt);
var backBtn = new Text2('BACK TO MENU', {
size: 60,
fill: 0xFF8000
});
backBtn.anchor.set(0.5, 0.5);
backBtn.x = 1024;
backBtn.y = 2000;
backBtn.visible = false;
game.addChild(backBtn);
var highScoreDetailTxt = new Text2('Best Score: ' + storage.highScore + '\nGames Played: ' + (storage.gamesPlayed || 0), {
size: 70,
fill: 0xFFFFFF
});
highScoreDetailTxt.anchor.set(0.5, 0.5);
highScoreDetailTxt.x = 1024;
highScoreDetailTxt.y = 1200;
highScoreDetailTxt.visible = false;
game.addChild(highScoreDetailTxt);
// Add sand elements at the bottom with realistic variation
var sandElements = [];
for (var i = 0; i < 15; i++) {
// Increased number for better coverage
// Create variation in sand height and positioning
var heightVariation = 0.4 + Math.random() * 0.5; // Height between 0.4x and 0.9x
var sandType = 'sand'; // Default sand type
var randomValue = Math.random();
if (randomValue < 0.3) {
sandType = 'sandLight'; // 30% chance for lighter sand
} else if (randomValue < 0.5) {
sandType = 'sandDark'; // 20% chance for darker sand
}
var sand = game.addChild(LK.getAsset(sandType, {
anchorX: 0,
anchorY: 1,
x: i * 140 + (Math.random() - 0.5) * 60,
// More horizontal variation for sandy texture
y: 2732 + Math.random() * 10 - 5,
// Less vertical variation for smoother sand
scaleY: heightVariation,
scaleX: 0.8 + Math.random() * 0.6,
// Width variation between 0.8x and 1.4x
rotation: (Math.random() - 0.5) * 0.1 // Minimal rotation for natural sand look
}));
sandElements.push(sand);
}
// Initialize airplane
airplane = game.addChild(new Airplane());
airplane.x = 400;
airplane.y = 1366;
// Update score display
function updateScore() {
scoreTxt.setText(LK.getScore());
if (LK.getScore() % 15 === 0) {
gameSpeed += 1;
buildingSpawnInterval = Math.max(150, buildingSpawnInterval - 5);
}
}
// Show/hide menu elements
function showMenu() {
gameState = 'menu';
titleTxt.visible = true;
playBtn.visible = true;
leaderboardBtn.visible = true;
highScoreTxt.visible = true;
leaderboardTitleTxt.visible = false;
backBtn.visible = false;
highScoreDetailTxt.visible = false;
scoreTxt.visible = false;
airplane.visible = false;
}
// Show/hide leaderboard elements
function showLeaderboard() {
gameState = 'leaderboard';
titleTxt.visible = false;
playBtn.visible = false;
leaderboardBtn.visible = false;
highScoreTxt.visible = false;
leaderboardTitleTxt.visible = true;
backBtn.visible = true;
highScoreDetailTxt.visible = true;
scoreTxt.visible = false;
airplane.visible = false;
// Update leaderboard text with top 3 scores
var globalScores = storage.globalScores || [];
globalScores.sort(function (a, b) {
return b - a;
});
var leaderboardText = 'TOP SCORES:\n\n';
if (globalScores.length >= 1) {
leaderboardText += '1st: ' + globalScores[0] + '\n';
}
if (globalScores.length >= 2) {
leaderboardText += '2nd: ' + globalScores[1] + '\n';
}
if (globalScores.length >= 3) {
leaderboardText += '3rd: ' + globalScores[2] + '\n';
}
if (globalScores.length === 0) {
leaderboardText += 'No scores yet!\nPlay to set a record!';
}
leaderboardText += '\n\nYour Best: ' + storage.highScore;
leaderboardText += '\nGames Played: ' + (storage.gamesPlayed || 0);
highScoreDetailTxt.setText(leaderboardText);
}
// Start game
function startGame() {
gameState = 'playing';
gameStarted = true;
titleTxt.visible = false;
playBtn.visible = false;
leaderboardBtn.visible = false;
highScoreTxt.visible = false;
leaderboardTitleTxt.visible = false;
backBtn.visible = false;
highScoreDetailTxt.visible = false;
scoreTxt.visible = true;
airplane.visible = true;
// Reset game variables
LK.setScore(0);
updateScore();
gameSpeed = 4;
buildingSpawnInterval = 220;
buildingSpawnTimer = 0;
// Clear any existing buildings
for (var i = buildings.length - 1; i >= 0; i--) {
buildings[i].destroy();
buildings.splice(i, 1);
}
// Reset airplane position
airplane.x = 400;
airplane.y = 1366;
airplane.velocity = 0;
// Spawn first building
spawnBuilding();
}
// Spawn new building
function spawnBuilding() {
var gapSize = 320; // Match the gap size used in Building class
var gapY = Math.floor(Math.random() * (2732 - gapSize - 600)) + 300; // Better gap positioning with margins
var building = new Building(0, 0, gapY);
building.x = 2048 + 100; // Start off-screen to the right
buildings.push(building);
game.addChild(building);
// Randomly decide whether to spawn a coin
if (Math.random() < 0.5) {
// 50% chance to spawn a coin
var coin = new Coin();
coin.x = building.x + 100; // Position coin in the middle of the gap
coin.y = gapY; // Align coin vertically with the gap
game.addChild(coin);
}
}
// Game input handling
game.down = function (x, y, obj) {
var currentTime = Date.now();
if (currentTime - lastTapTime < tapCooldown) {
return; // Too soon, ignore this tap
}
lastTapTime = currentTime;
if (gameState === 'menu') {
// Check if play button was tapped
if (x >= playBtn.x - 100 && x <= playBtn.x + 100 && y >= playBtn.y - 40 && y <= playBtn.y + 40) {
startGame();
return;
}
// Check if leaderboard button was tapped
if (x >= leaderboardBtn.x - 150 && x <= leaderboardBtn.x + 150 && y >= leaderboardBtn.y - 30 && y <= leaderboardBtn.y + 30) {
showLeaderboard();
return;
}
} else if (gameState === 'leaderboard') {
// Check if back button was tapped
if (x >= backBtn.x - 120 && x <= backBtn.x + 120 && y >= backBtn.y - 30 && y <= backBtn.y + 30) {
showMenu();
return;
}
} else if (gameState === 'playing') {
airplane.jump();
}
};
// Main game loop
game.update = function () {
if (gameState !== 'playing' || !gameStarted) return;
// Update building spawn timer
buildingSpawnTimer++;
if (buildingSpawnTimer >= buildingSpawnInterval) {
buildingSpawnTimer = 0;
spawnBuilding();
// Gradually increase difficulty
if (buildingSpawnInterval > 150) {
buildingSpawnInterval -= 0.1;
}
}
// Check collisions and update buildings
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
// Check collision
if (building.checkCollision(airplane)) {
// Save high score and update statistics
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Add score to global leaderboard
var globalScores = storage.globalScores || [];
globalScores.push(LK.getScore());
storage.globalScores = globalScores;
storage.gamesPlayed = (storage.gamesPlayed || 0) + 1;
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
// Reset to menu after game over
gameStarted = false;
showMenu();
return;
}
// Check if airplane passed building (score)
if (!building.passed && building.x + 200 < airplane.x) {
building.passed = true;
LK.setScore(LK.getScore() + 1);
updateScore();
}
// Remove buildings that are off-screen
if (building.x < -400) {
building.destroy();
buildings.splice(i, 1);
}
// Check for collisions with coins
var coins = game.children.filter(function (child) {
return child instanceof Coin;
});
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
// Manual collision detection for coins using proper airplane dimensions
var airplaneScaledWidth = 120 * 2.2;
var airplaneScaledHeight = 60 * 2.2;
var airplaneLeft = airplane.x - airplaneScaledWidth / 2;
var airplaneRight = airplane.x + airplaneScaledWidth / 2;
var airplaneTop = airplane.y - airplaneScaledHeight / 2;
var airplaneBottom = airplane.y + airplaneScaledHeight / 2;
var coinLeft = coin.x - 25; // coin width/2 = 50/2 = 25
var coinRight = coin.x + 25;
var coinTop = coin.y - 25; // coin height/2 = 50/2 = 25
var coinBottom = coin.y + 25;
// Check if rectangles overlap
if (airplaneRight > coinLeft && airplaneLeft < coinRight && airplaneBottom > coinTop && airplaneTop < coinBottom) {
LK.setScore(LK.getScore() + 2); // Increase score by 2 for collecting a coin
updateScore();
coin.destroy();
coins.splice(j, 1);
}
}
}
// Check ground and ceiling collision
if (airplane.y <= 30 || airplane.y >= 2702) {
// Save high score and update statistics
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Add score to global leaderboard
var globalScores = storage.globalScores || [];
globalScores.push(LK.getScore());
storage.globalScores = globalScores;
storage.gamesPlayed = (storage.gamesPlayed || 0) + 1;
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
// Reset to menu after game over
gameStarted = false;
showMenu();
return;
}
// Animate fish shadows
for (var k = 0; k < fishShadows.length; k++) {
var shadow = fishShadows[k];
shadow.x += shadow.speedX;
shadow.y += shadow.speedY;
// Add subtle vertical oscillation for realistic swimming motion
shadow.y += Math.sin(LK.ticks * 0.02 + k) * 0.5;
// Reset fish position when it goes off screen
if (shadow.x < -100) {
shadow.x = 2200 + Math.random() * 100;
shadow.y = 1200 + Math.random() * 1000;
shadow.speedX = -0.5 - Math.random() * 1.5;
shadow.speedY = (Math.random() - 0.5) * 0.3;
}
// Keep fish shadows within reasonable depth bounds
if (shadow.y < 1100) shadow.y = 1100;
if (shadow.y > 2400) shadow.y = 2400;
}
// Animate clouds
for (var c = 0; c < clouds.length; c++) {
var cloud = clouds[c];
cloud.x += cloud.speedX;
// Reset cloud position when it goes off screen
if (cloud.x < -200) {
cloud.x = 2400 + Math.random() * 200;
cloud.y = 200 + Math.random() * 400;
}
}
};
// Initialize score display
updateScore();
// Initialize game in menu state
showMenu();
// Add pause message text (initially hidden)
var pauseWarningTxt = new Text2('YOU CANT STOP IN MY GAME', {
size: 80,
fill: 0xFF0000
});
pauseWarningTxt.anchor.set(0.5, 0);
pauseWarningTxt.x = 1024;
pauseWarningTxt.y = 50;
pauseWarningTxt.visible = false;
game.addChild(pauseWarningTxt);
// Override pause event to prevent pausing and show warning
LK.on('pause', function () {
// Show red warning message
pauseWarningTxt.visible = true;
// Hide message after 2 seconds
LK.setTimeout(function () {
pauseWarningTxt.visible = false;
}, 2000);
// Prevent default pause behavior by returning false
return false;
});
// Start background music
LK.playMusic('arkaplan');
; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
gamesPlayed: 0,
globalScores: []
});
/****
* Classes
****/
var Airplane = Container.expand(function () {
var self = Container.call(this);
var airplaneGraphics = self.attachAsset('airplane', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
self.velocity = 0;
self.gravity = 0.6;
self.jumpPower = -10;
self.maxVelocity = 12;
self.update = function () {
// Apply gravity
self.velocity += self.gravity;
// Limit velocity
if (self.velocity > self.maxVelocity) {
self.velocity = self.maxVelocity;
}
if (self.velocity < -self.maxVelocity) {
self.velocity = -self.maxVelocity;
}
// Update position
self.y += self.velocity;
// Rotate airplane based on velocity for visual effect
airplaneGraphics.rotation = Math.max(-0.5, Math.min(0.5, self.velocity * 0.05));
// Allow airplane to go off screen (will be caught by game over logic)
};
self.jump = function () {
self.velocity = self.jumpPower;
LK.getSound('fly').play();
};
return self;
});
var Building = Container.expand(function (topHeight, bottomHeight, gapY) {
var self = Container.call(this);
var gapSize = 320;
// Top building
var topBuilding = self.attachAsset('building', {
anchorX: 0,
anchorY: 1,
scaleY: (gapY - gapSize / 2) / 100,
rotation: 0 // Revert the rotation of the top building to its original orientation
});
topBuilding.y = gapY - gapSize / 2; // Position top building at gap start
// Bottom building
var bottomBuilding = self.attachAsset('building', {
anchorX: 0,
anchorY: 0,
scaleY: (2732 - (gapY + gapSize / 2)) / 100
});
bottomBuilding.y = gapY + gapSize / 2; // Position bottom building at gap end
self.speed = -4;
self.passed = false;
self.update = function () {
self.x += self.speed;
};
self.checkCollision = function (airplane) {
// Get airplane's actual scaled dimensions with reduced hitbox for better gameplay
var airplaneScaledWidth = 120 * 2.2 * 0.7; // Reduce hitbox by 30%
var airplaneScaledHeight = 60 * 2.2 * 0.7; // Reduce hitbox by 30%
var airplaneLeft = airplane.x - airplaneScaledWidth / 2;
var airplaneRight = airplane.x + airplaneScaledWidth / 2;
var airplaneTop = airplane.y - airplaneScaledHeight / 2;
var airplaneBottom = airplane.y + airplaneScaledHeight / 2;
// Get building dimensions (no scaling applied to buildings, so use original width)
var buildingWidth = 175;
var buildingLeft = self.x + 10; // Add small margin to building hitbox
var buildingRight = self.x + buildingWidth - 10; // Reduce building hitbox width
// Check if airplane is within building's x range
if (airplaneRight > buildingLeft && airplaneLeft < buildingRight) {
// Check collision with top building (add small margin)
if (airplaneTop < topBuilding.y - 5) {
return true;
}
// Check collision with bottom building (add small margin)
if (airplaneBottom > bottomBuilding.y + 5) {
return true;
}
}
return false;
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.update = function () {
self.x += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB,
scale: 2.0 // Reduce the scale to make the screen appear smaller
});
/****
* Game Code
****/
// Add sea background
var seaBg = game.addChild(LK.getAsset('seaBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Add fish shadows in the sea
var fishShadows = [];
for (var i = 0; i < 12; i++) {
var shadowType = 'fishShadow' + (Math.floor(Math.random() * 3) + 1);
var fishShadow = game.addChild(LK.getAsset(shadowType, {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2200,
y: 1200 + Math.random() * 1000,
alpha: 0.15 + Math.random() * 0.25,
scaleX: 0.8 + Math.random() * 0.4,
scaleY: 0.8 + Math.random() * 0.4
}));
fishShadow.speedX = -0.5 - Math.random() * 1.5;
fishShadow.speedY = (Math.random() - 0.5) * 0.3;
fishShadow.originalX = fishShadow.x;
fishShadow.originalY = fishShadow.y;
fishShadows.push(fishShadow);
}
// Add clouds in the sky
var clouds = [];
for (var i = 0; i < 6; i++) {
var cloud = game.addChild(LK.getAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2400,
y: 200 + Math.random() * 400,
alpha: 0.6 + Math.random() * 0.3,
scaleX: 1.2 + Math.random() * 0.8,
scaleY: 0.8 + Math.random() * 0.6
}));
cloud.speedX = -0.2 - Math.random() * 0.3;
clouds.push(cloud);
}
// Game variables
var airplane;
var buildings = [];
var gameSpeed = 4;
var buildingSpawnTimer = 0;
var buildingSpawnInterval = 220; // frames between buildings
var gameStarted = false;
var lastTapTime = 0;
var tapCooldown = 50; // milliseconds between taps (20 taps per second max)
// Menu state variables
var gameState = 'menu'; // 'menu', 'playing', 'leaderboard'
var menuButtons = [];
// UI Elements
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Menu UI elements
var titleTxt = new Text2('9/11', {
size: 120,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.x = 1024;
titleTxt.y = 800;
game.addChild(titleTxt);
var playBtn = new Text2('PLAY', {
size: 80,
fill: 0x00FF00
});
playBtn.anchor.set(0.5, 0.5);
playBtn.x = 1024;
playBtn.y = 1200;
game.addChild(playBtn);
var leaderboardBtn = new Text2('LEADERBOARD', {
size: 60,
fill: 0x0080FF
});
leaderboardBtn.anchor.set(0.5, 0.5);
leaderboardBtn.x = 1024;
leaderboardBtn.y = 1350;
game.addChild(leaderboardBtn);
var highScoreTxt = new Text2('HIGH SCORE: ' + storage.highScore, {
size: 60,
fill: 0xFFD700
});
highScoreTxt.anchor.set(0.5, 0.5);
highScoreTxt.x = 1024;
highScoreTxt.y = 1050;
game.addChild(highScoreTxt);
// Leaderboard UI elements (initially hidden)
var leaderboardTitleTxt = new Text2('LEADERBOARD', {
size: 100,
fill: 0xFFFFFF
});
leaderboardTitleTxt.anchor.set(0.5, 0.5);
leaderboardTitleTxt.x = 1024;
leaderboardTitleTxt.y = 600;
leaderboardTitleTxt.visible = false;
game.addChild(leaderboardTitleTxt);
var backBtn = new Text2('BACK TO MENU', {
size: 60,
fill: 0xFF8000
});
backBtn.anchor.set(0.5, 0.5);
backBtn.x = 1024;
backBtn.y = 2000;
backBtn.visible = false;
game.addChild(backBtn);
var highScoreDetailTxt = new Text2('Best Score: ' + storage.highScore + '\nGames Played: ' + (storage.gamesPlayed || 0), {
size: 70,
fill: 0xFFFFFF
});
highScoreDetailTxt.anchor.set(0.5, 0.5);
highScoreDetailTxt.x = 1024;
highScoreDetailTxt.y = 1200;
highScoreDetailTxt.visible = false;
game.addChild(highScoreDetailTxt);
// Add sand elements at the bottom with realistic variation
var sandElements = [];
for (var i = 0; i < 15; i++) {
// Increased number for better coverage
// Create variation in sand height and positioning
var heightVariation = 0.4 + Math.random() * 0.5; // Height between 0.4x and 0.9x
var sandType = 'sand'; // Default sand type
var randomValue = Math.random();
if (randomValue < 0.3) {
sandType = 'sandLight'; // 30% chance for lighter sand
} else if (randomValue < 0.5) {
sandType = 'sandDark'; // 20% chance for darker sand
}
var sand = game.addChild(LK.getAsset(sandType, {
anchorX: 0,
anchorY: 1,
x: i * 140 + (Math.random() - 0.5) * 60,
// More horizontal variation for sandy texture
y: 2732 + Math.random() * 10 - 5,
// Less vertical variation for smoother sand
scaleY: heightVariation,
scaleX: 0.8 + Math.random() * 0.6,
// Width variation between 0.8x and 1.4x
rotation: (Math.random() - 0.5) * 0.1 // Minimal rotation for natural sand look
}));
sandElements.push(sand);
}
// Initialize airplane
airplane = game.addChild(new Airplane());
airplane.x = 400;
airplane.y = 1366;
// Update score display
function updateScore() {
scoreTxt.setText(LK.getScore());
if (LK.getScore() % 15 === 0) {
gameSpeed += 1;
buildingSpawnInterval = Math.max(150, buildingSpawnInterval - 5);
}
}
// Show/hide menu elements
function showMenu() {
gameState = 'menu';
titleTxt.visible = true;
playBtn.visible = true;
leaderboardBtn.visible = true;
highScoreTxt.visible = true;
leaderboardTitleTxt.visible = false;
backBtn.visible = false;
highScoreDetailTxt.visible = false;
scoreTxt.visible = false;
airplane.visible = false;
}
// Show/hide leaderboard elements
function showLeaderboard() {
gameState = 'leaderboard';
titleTxt.visible = false;
playBtn.visible = false;
leaderboardBtn.visible = false;
highScoreTxt.visible = false;
leaderboardTitleTxt.visible = true;
backBtn.visible = true;
highScoreDetailTxt.visible = true;
scoreTxt.visible = false;
airplane.visible = false;
// Update leaderboard text with top 3 scores
var globalScores = storage.globalScores || [];
globalScores.sort(function (a, b) {
return b - a;
});
var leaderboardText = 'TOP SCORES:\n\n';
if (globalScores.length >= 1) {
leaderboardText += '1st: ' + globalScores[0] + '\n';
}
if (globalScores.length >= 2) {
leaderboardText += '2nd: ' + globalScores[1] + '\n';
}
if (globalScores.length >= 3) {
leaderboardText += '3rd: ' + globalScores[2] + '\n';
}
if (globalScores.length === 0) {
leaderboardText += 'No scores yet!\nPlay to set a record!';
}
leaderboardText += '\n\nYour Best: ' + storage.highScore;
leaderboardText += '\nGames Played: ' + (storage.gamesPlayed || 0);
highScoreDetailTxt.setText(leaderboardText);
}
// Start game
function startGame() {
gameState = 'playing';
gameStarted = true;
titleTxt.visible = false;
playBtn.visible = false;
leaderboardBtn.visible = false;
highScoreTxt.visible = false;
leaderboardTitleTxt.visible = false;
backBtn.visible = false;
highScoreDetailTxt.visible = false;
scoreTxt.visible = true;
airplane.visible = true;
// Reset game variables
LK.setScore(0);
updateScore();
gameSpeed = 4;
buildingSpawnInterval = 220;
buildingSpawnTimer = 0;
// Clear any existing buildings
for (var i = buildings.length - 1; i >= 0; i--) {
buildings[i].destroy();
buildings.splice(i, 1);
}
// Reset airplane position
airplane.x = 400;
airplane.y = 1366;
airplane.velocity = 0;
// Spawn first building
spawnBuilding();
}
// Spawn new building
function spawnBuilding() {
var gapSize = 320; // Match the gap size used in Building class
var gapY = Math.floor(Math.random() * (2732 - gapSize - 600)) + 300; // Better gap positioning with margins
var building = new Building(0, 0, gapY);
building.x = 2048 + 100; // Start off-screen to the right
buildings.push(building);
game.addChild(building);
// Randomly decide whether to spawn a coin
if (Math.random() < 0.5) {
// 50% chance to spawn a coin
var coin = new Coin();
coin.x = building.x + 100; // Position coin in the middle of the gap
coin.y = gapY; // Align coin vertically with the gap
game.addChild(coin);
}
}
// Game input handling
game.down = function (x, y, obj) {
var currentTime = Date.now();
if (currentTime - lastTapTime < tapCooldown) {
return; // Too soon, ignore this tap
}
lastTapTime = currentTime;
if (gameState === 'menu') {
// Check if play button was tapped
if (x >= playBtn.x - 100 && x <= playBtn.x + 100 && y >= playBtn.y - 40 && y <= playBtn.y + 40) {
startGame();
return;
}
// Check if leaderboard button was tapped
if (x >= leaderboardBtn.x - 150 && x <= leaderboardBtn.x + 150 && y >= leaderboardBtn.y - 30 && y <= leaderboardBtn.y + 30) {
showLeaderboard();
return;
}
} else if (gameState === 'leaderboard') {
// Check if back button was tapped
if (x >= backBtn.x - 120 && x <= backBtn.x + 120 && y >= backBtn.y - 30 && y <= backBtn.y + 30) {
showMenu();
return;
}
} else if (gameState === 'playing') {
airplane.jump();
}
};
// Main game loop
game.update = function () {
if (gameState !== 'playing' || !gameStarted) return;
// Update building spawn timer
buildingSpawnTimer++;
if (buildingSpawnTimer >= buildingSpawnInterval) {
buildingSpawnTimer = 0;
spawnBuilding();
// Gradually increase difficulty
if (buildingSpawnInterval > 150) {
buildingSpawnInterval -= 0.1;
}
}
// Check collisions and update buildings
for (var i = buildings.length - 1; i >= 0; i--) {
var building = buildings[i];
// Check collision
if (building.checkCollision(airplane)) {
// Save high score and update statistics
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Add score to global leaderboard
var globalScores = storage.globalScores || [];
globalScores.push(LK.getScore());
storage.globalScores = globalScores;
storage.gamesPlayed = (storage.gamesPlayed || 0) + 1;
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
// Reset to menu after game over
gameStarted = false;
showMenu();
return;
}
// Check if airplane passed building (score)
if (!building.passed && building.x + 200 < airplane.x) {
building.passed = true;
LK.setScore(LK.getScore() + 1);
updateScore();
}
// Remove buildings that are off-screen
if (building.x < -400) {
building.destroy();
buildings.splice(i, 1);
}
// Check for collisions with coins
var coins = game.children.filter(function (child) {
return child instanceof Coin;
});
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
// Manual collision detection for coins using proper airplane dimensions
var airplaneScaledWidth = 120 * 2.2;
var airplaneScaledHeight = 60 * 2.2;
var airplaneLeft = airplane.x - airplaneScaledWidth / 2;
var airplaneRight = airplane.x + airplaneScaledWidth / 2;
var airplaneTop = airplane.y - airplaneScaledHeight / 2;
var airplaneBottom = airplane.y + airplaneScaledHeight / 2;
var coinLeft = coin.x - 25; // coin width/2 = 50/2 = 25
var coinRight = coin.x + 25;
var coinTop = coin.y - 25; // coin height/2 = 50/2 = 25
var coinBottom = coin.y + 25;
// Check if rectangles overlap
if (airplaneRight > coinLeft && airplaneLeft < coinRight && airplaneBottom > coinTop && airplaneTop < coinBottom) {
LK.setScore(LK.getScore() + 2); // Increase score by 2 for collecting a coin
updateScore();
coin.destroy();
coins.splice(j, 1);
}
}
}
// Check ground and ceiling collision
if (airplane.y <= 30 || airplane.y >= 2702) {
// Save high score and update statistics
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
// Add score to global leaderboard
var globalScores = storage.globalScores || [];
globalScores.push(LK.getScore());
storage.globalScores = globalScores;
storage.gamesPlayed = (storage.gamesPlayed || 0) + 1;
highScoreTxt.setText('HIGH SCORE: ' + storage.highScore);
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
// Reset to menu after game over
gameStarted = false;
showMenu();
return;
}
// Animate fish shadows
for (var k = 0; k < fishShadows.length; k++) {
var shadow = fishShadows[k];
shadow.x += shadow.speedX;
shadow.y += shadow.speedY;
// Add subtle vertical oscillation for realistic swimming motion
shadow.y += Math.sin(LK.ticks * 0.02 + k) * 0.5;
// Reset fish position when it goes off screen
if (shadow.x < -100) {
shadow.x = 2200 + Math.random() * 100;
shadow.y = 1200 + Math.random() * 1000;
shadow.speedX = -0.5 - Math.random() * 1.5;
shadow.speedY = (Math.random() - 0.5) * 0.3;
}
// Keep fish shadows within reasonable depth bounds
if (shadow.y < 1100) shadow.y = 1100;
if (shadow.y > 2400) shadow.y = 2400;
}
// Animate clouds
for (var c = 0; c < clouds.length; c++) {
var cloud = clouds[c];
cloud.x += cloud.speedX;
// Reset cloud position when it goes off screen
if (cloud.x < -200) {
cloud.x = 2400 + Math.random() * 200;
cloud.y = 200 + Math.random() * 400;
}
}
};
// Initialize score display
updateScore();
// Initialize game in menu state
showMenu();
// Add pause message text (initially hidden)
var pauseWarningTxt = new Text2('YOU CANT STOP IN MY GAME', {
size: 80,
fill: 0xFF0000
});
pauseWarningTxt.anchor.set(0.5, 0);
pauseWarningTxt.x = 1024;
pauseWarningTxt.y = 50;
pauseWarningTxt.visible = false;
game.addChild(pauseWarningTxt);
// Override pause event to prevent pausing and show warning
LK.on('pause', function () {
// Show red warning message
pauseWarningTxt.visible = true;
// Hide message after 2 seconds
LK.setTimeout(function () {
pauseWarningTxt.visible = false;
}, 2000);
// Prevent default pause behavior by returning false
return false;
});
// Start background music
LK.playMusic('arkaplan');
;