/**** * Classes ****/ var Bird = Container.expand(function () { var self = Container.call(this); var birdGraphics = self.attachAsset('bird', { anchorX: 0.5, anchorY: 0.5 }); self.velocity = 0; // Don't set gravity and jumpStrength here as gameSpeed may not be initialized yet // They will be set dynamically in update method self.flap = function () { // Set velocity with more balanced scaling for consistent control self.velocity = baseJumpStrength * Math.pow(gameSpeed, 0.8) * 1.05; // More balanced power scaling // Create natural wing flap animation with squash and stretch tween(birdGraphics, { scaleX: 1.3, scaleY: 0.8, rotation: -0.4 }, { duration: 80, easing: tween.easeOut, onFinish: function onFinish() { // Secondary animation for natural wing movement tween(birdGraphics, { scaleX: 0.9, scaleY: 1.1, rotation: -0.2 }, { duration: 120, easing: tween.easeInOut, onFinish: function onFinish() { // Return to normal with slight overshoot for natural feel tween(birdGraphics, { scaleX: 1.05, scaleY: 0.95, rotation: 0.1 }, { duration: 150, easing: tween.easeOut, onFinish: function onFinish() { tween(birdGraphics, { scaleX: 1.0, scaleY: 1.0, rotation: 0 }, { duration: 100, easing: tween.easeInOut }); } }); } }); } }); // Create natural arc movement - bird moves slightly forward and up during flap var currentX = self.x; var currentY = self.y; // First part of arc - upward and slightly forward tween(self, { x: currentX + 15, y: currentY - 25 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { // Second part of arc - continue forward motion with natural deceleration tween(self, { x: currentX + 8 }, { duration: 200, easing: tween.easeInOut }); } }); // Add slight horizontal bob for more natural movement tween(birdGraphics, { x: 3 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(birdGraphics, { x: -2 }, { duration: 180, easing: tween.easeInOut, onFinish: function onFinish() { tween(birdGraphics, { x: 0 }, { duration: 100, easing: tween.easeOut }); } }); } }); try { var flapSound = LK.getSound('flap'); if (flapSound && flapSound.play) { flapSound.play(); } } catch (e) { console.log("Flap sound error:", e); } }; self.update = function () { if (!gameStarted) { // Don't apply physics before game starts - keep bird completely still self.velocity = 0; self.y = 1366; // Keep bird at starting position birdGraphics.rotation = 0; // Keep bird level return; } // Update dynamic values based on current game speed with more balanced scaling var gravity = baseGravity * Math.pow(gameSpeed, 0.7); // More balanced gravity scaling var jumpStrength = baseJumpStrength * Math.pow(gameSpeed, 0.75); // More balanced jump scaling self.velocity += gravity; self.y += self.velocity; // More responsive rotation based on velocity with better scaling var rotationScale = 0.065 + (gameSpeed - 1) * 0.015; // Slightly more responsive at higher speeds var targetRotation = Math.max(-0.5, Math.min(1.1, self.velocity * rotationScale)); // Smooth rotation transition using tween for more natural movement if (Math.abs(birdGraphics.rotation - targetRotation) > 0.04) { tween(birdGraphics, { rotation: targetRotation }, { duration: 120, easing: tween.easeOut }); } // Limit bird movement to screen bounds with proper collision detection var birdRadius = 40; // Half of bird height for collision detection if (self.y - birdRadius < 0) { self.y = birdRadius; self.velocity = 0; } if (self.y + birdRadius > 2732 - 150) { self.y = 2732 - 150 - birdRadius; self.velocity = 0; } }; return self; }); var Pipe = Container.expand(function (gapCenterY) { var self = Container.call(this); self.gapSize = 750 + (gameSpeed - 1) * 50; // Dynamic gap size based on speed for better balance self.speed = basePipeSpeed * gameSpeed; self.passed = false; self.gapCenterY = gapCenterY; // Store pipe width for consistent collision detection self.pipeWidth = 120; // Calculate pipe heights var topPipeHeight = Math.max(200, gapCenterY - self.gapSize / 2); var bottomPipeHeight = Math.max(200, 2732 - 150 - (gapCenterY + self.gapSize / 2)); // =============== TOP PIPE CONSTRUCTION =============== // Create main top pipe body with darker base color var topPipe = self.attachAsset('topPipe', { anchorX: 0.5, anchorY: 1 }); topPipe.y = gapCenterY - self.gapSize / 2; topPipe.height = topPipeHeight; topPipe.width = self.pipeWidth; topPipe.tint = 0x1B5E20; // Dark forest green base // Create pipe shadow for depth var topPipeShadow = self.attachAsset('topPipe', { anchorX: 0.5, anchorY: 1 }); topPipeShadow.y = gapCenterY - self.gapSize / 2; topPipeShadow.height = topPipeHeight; topPipeShadow.width = self.pipeWidth + 6; topPipeShadow.x = 3; topPipeShadow.tint = 0x0D2818; // Very dark shadow topPipeShadow.alpha = 0.4; // Create multiple highlight layers for realistic metallic sheen var topPipeHighlight1 = self.attachAsset('pipeHighlight', { anchorX: 0.5, anchorY: 1 }); topPipeHighlight1.y = gapCenterY - self.gapSize / 2; topPipeHighlight1.height = topPipeHeight; topPipeHighlight1.width = 25; topPipeHighlight1.x = -35; topPipeHighlight1.tint = 0x66BB6A; // Bright green highlight topPipeHighlight1.alpha = 0.8; var topPipeHighlight2 = self.attachAsset('pipeHighlight', { anchorX: 0.5, anchorY: 1 }); topPipeHighlight2.y = gapCenterY - self.gapSize / 2; topPipeHighlight2.height = topPipeHeight; topPipeHighlight2.width = 12; topPipeHighlight2.x = -42; topPipeHighlight2.tint = 0xA5D6A7; // Lighter green shine topPipeHighlight2.alpha = 0.9; // Create realistic pipe joint rings every 150px var numJoints = Math.floor(topPipeHeight / 150); for (var j = 0; j < numJoints; j++) { var jointY = gapCenterY - self.gapSize / 2 - (j + 1) * 150; if (jointY > 50 && jointY < gapCenterY - self.gapSize / 2 - 50) { // Don't create joints too close to top or gap area // Main joint ring var topJoint = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 0.5 }); topJoint.y = jointY; topJoint.width = self.pipeWidth + 15; topJoint.height = 20; topJoint.tint = 0x37474F; // Blue-gray metallic // Joint highlight var topJointHighlight = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 0.5 }); topJointHighlight.y = jointY - 3; topJointHighlight.width = self.pipeWidth + 12; topJointHighlight.height = 8; topJointHighlight.tint = 0x78909C; // Lighter metallic topJointHighlight.alpha = 0.7; } } // Rivets removed to prevent visual elements in gap area // Enhanced top pipe cap with multiple layers var topPipeCapBase = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 1 }); topPipeCapBase.y = gapCenterY - self.gapSize / 2; topPipeCapBase.width = self.pipeWidth + 45; topPipeCapBase.height = 35; topPipeCapBase.tint = 0x263238; // Very dark base var topPipeCap = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 1 }); topPipeCap.y = gapCenterY - self.gapSize / 2; topPipeCap.width = self.pipeWidth + 35; topPipeCap.height = 30; topPipeCap.tint = 0x37474F; // Dark metallic var topCapHighlight = self.attachAsset('pipeTop', { anchorX: 0.5, anchorY: 1 }); topCapHighlight.y = gapCenterY - self.gapSize / 2; topCapHighlight.width = self.pipeWidth + 30; topCapHighlight.height = 12; topCapHighlight.tint = 0x78909C; // Metallic highlight topCapHighlight.alpha = 0.8; // =============== BOTTOM PIPE CONSTRUCTION =============== // Create main bottom pipe body with darker base color var bottomPipe = self.attachAsset('bottomPipe', { anchorX: 0.5, anchorY: 0 }); bottomPipe.y = gapCenterY + self.gapSize / 2; bottomPipe.height = bottomPipeHeight; bottomPipe.width = self.pipeWidth; bottomPipe.tint = 0x1B5E20; // Dark forest green base // Create pipe shadow for depth var bottomPipeShadow = self.attachAsset('bottomPipe', { anchorX: 0.5, anchorY: 0 }); bottomPipeShadow.y = gapCenterY + self.gapSize / 2; bottomPipeShadow.height = bottomPipeHeight; bottomPipeShadow.width = self.pipeWidth + 6; bottomPipeShadow.x = 3; bottomPipeShadow.tint = 0x0D2818; // Very dark shadow bottomPipeShadow.alpha = 0.4; // Create multiple highlight layers for realistic metallic sheen var bottomPipeHighlight1 = self.attachAsset('pipeHighlight', { anchorX: 0.5, anchorY: 0 }); bottomPipeHighlight1.y = gapCenterY + self.gapSize / 2; bottomPipeHighlight1.height = bottomPipeHeight; bottomPipeHighlight1.width = 25; bottomPipeHighlight1.x = -35; bottomPipeHighlight1.tint = 0x66BB6A; // Bright green highlight bottomPipeHighlight1.alpha = 0.8; var bottomPipeHighlight2 = self.attachAsset('pipeHighlight', { anchorX: 0.5, anchorY: 0 }); bottomPipeHighlight2.y = gapCenterY + self.gapSize / 2; bottomPipeHighlight2.height = bottomPipeHeight; bottomPipeHighlight2.width = 12; bottomPipeHighlight2.x = -42; bottomPipeHighlight2.tint = 0xA5D6A7; // Lighter green shine bottomPipeHighlight2.alpha = 0.9; // Create realistic pipe joint rings every 150px var numBottomJoints = Math.floor(bottomPipeHeight / 150); for (var j = 0; j < numBottomJoints; j++) { var jointY = gapCenterY + self.gapSize / 2 + (j + 1) * 150; if (jointY < 2732 - 200) { // Don't create joints too close to ground // Main joint ring var bottomJoint = self.attachAsset('pipeBottom', { anchorX: 0.5, anchorY: 0.5 }); bottomJoint.y = jointY; bottomJoint.width = self.pipeWidth + 15; bottomJoint.height = 20; bottomJoint.tint = 0x37474F; // Blue-gray metallic // Joint highlight var bottomJointHighlight = self.attachAsset('pipeBottom', { anchorX: 0.5, anchorY: 0.5 }); bottomJointHighlight.y = jointY + 3; bottomJointHighlight.width = self.pipeWidth + 12; bottomJointHighlight.height = 8; bottomJointHighlight.tint = 0x78909C; // Lighter metallic bottomJointHighlight.alpha = 0.7; } } // Rivets removed to prevent visual elements in gap area // Enhanced bottom pipe cap with multiple layers var bottomPipeCapBase = self.attachAsset('pipeBottom', { anchorX: 0.5, anchorY: 0 }); bottomPipeCapBase.y = gapCenterY + self.gapSize / 2; bottomPipeCapBase.width = self.pipeWidth + 45; bottomPipeCapBase.height = 35; bottomPipeCapBase.tint = 0x263238; // Very dark base var bottomPipeCap = self.attachAsset('pipeBottom', { anchorX: 0.5, anchorY: 0 }); bottomPipeCap.y = gapCenterY + self.gapSize / 2; bottomPipeCap.width = self.pipeWidth + 35; bottomPipeCap.height = 30; bottomPipeCap.tint = 0x37474F; // Dark metallic var bottomCapHighlight = self.attachAsset('pipeBottom', { anchorX: 0.5, anchorY: 0 }); bottomCapHighlight.y = gapCenterY + self.gapSize / 2; bottomCapHighlight.width = self.pipeWidth + 30; bottomCapHighlight.height = 12; bottomCapHighlight.tint = 0x78909C; // Metallic highlight bottomCapHighlight.alpha = 0.8; self.update = function () { if (!gameStarted) { // Don't move pipes before game starts return; } // Update dynamic speed based on current game speed self.speed = basePipeSpeed * gameSpeed; self.x += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game(); /**** * Game Code ****/ // Initialize plugins with proper error handling // Game variables var tween; var storage; try { tween = LK.import("@upit/tween.v1"); storage = LK.import("@upit/storage.v1", { highScore: 0, language: 'en', username: 'Player1', globalLeaderboardNames: [], globalLeaderboardScores: [], lastScore: 0 }); } catch (e) { console.log("Plugin import error:", e); // Provide comprehensive fallback objects to prevent undefined errors tween = function tween(target, props, options) { return { duration: options ? options.duration || 0 : 0, onFinish: options && options.onFinish ? options.onFinish : function () {} }; }; storage = { highScore: 0, language: 'en', username: 'Player1', globalLeaderboardNames: [], globalLeaderboardScores: [], lastScore: 0 }; } var bird; var pipes = []; var ground; var topBarrier; var bottomBarrier; var gameStarted = false; var gameOver = false; var showMainMenu = true; var showGameOver = false; var pipeSpacing = 500 + gameSpeed * 50; // Dynamic spacing based on speed for better balance var buttonClickTimeout = null; // Prevent rapid button clicks var lastButtonClickTime = 0; // Track last button click time var gameSpeed = 1; // Current game speed multiplier (1 = normal, 2 = 2x, 3 = 3x) var baseGravity = 0.55; // Base gravity for bird - fine-tuned for better control var baseJumpStrength = -9.5; // Base jump strength for bird - fine-tuned for better balance var basePipeSpeed = -3; // Base pipe movement speed // Initialize game speed properly gameSpeed = 1; // Initialize storage with defaults var _storage = storage; // Create score text display var scoreTxt = new Text2('0', { size: 150, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); scoreTxt.stroke = 0x000000; scoreTxt.strokeThickness = 5; try { if (LK.gui && LK.gui.top) { LK.gui.top.addChild(scoreTxt); } } catch (e) { console.log("GUI score text error:", e); } // Create cup shape for score var cupShape; try { cupShape = LK.getAsset('cup', { anchorX: 0.5, anchorY: 0 }); cupShape.tint = 0xFFD700; if (LK.gui && LK.gui.bottomRight) { LK.gui.bottomRight.addChild(cupShape); cupShape.y = -230; cupShape.x = -100; } } catch (e) { console.log("Cup shape error:", e); } // Create main menu elements var mainMenuTitle = new Text2('FLAPPY BIRD', { size: 90, fill: 0xFFD700 }); mainMenuTitle.anchor.set(0.5, 0.5); mainMenuTitle.stroke = 0x000000; mainMenuTitle.strokeThickness = 5; try { if (LK.gui && LK.gui.center) { LK.gui.center.addChild(mainMenuTitle); mainMenuTitle.y = -280; } } catch (e) { console.log("Main menu title error:", e); } // Create instruction text var instructionTxt = new Text2('TIKLA VE OYNA!', { size: 50, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 0.5); instructionTxt.stroke = 0x000000; instructionTxt.strokeThickness = 3; instructionTxt.visible = false; instructionTxt.y = -50; // Remove background shape for instruction text - no longer needed LK.gui.center.addChild(instructionTxt); // Create game over screen elements var gameOverBg = LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0.5, width: 1600, height: 1200, alpha: 0.95 }); gameOverBg.tint = 0x2F4F4F; gameOverBg.visible = false; LK.gui.center.addChild(gameOverBg); var gameOverTitle = new Text2('OYUN BİTTİ', { size: 120, fill: 0xFFFFFF }); gameOverTitle.anchor.set(0.5, 0.5); gameOverTitle.stroke = 0x000000; gameOverTitle.strokeThickness = 6; gameOverTitle.visible = false; LK.gui.center.addChild(gameOverTitle); gameOverTitle.y = -300; var finalScoreText = new Text2('SKOR: 0', { size: 80, fill: 0xFFFFFF }); finalScoreText.anchor.set(0.5, 0.5); finalScoreText.stroke = 0x000000; finalScoreText.strokeThickness = 4; finalScoreText.visible = false; LK.gui.center.addChild(finalScoreText); finalScoreText.y = -150; var bestScoreText = new Text2('EN İYİ: 0', { size: 60, fill: 0xFFD700 }); bestScoreText.anchor.set(0.5, 0.5); bestScoreText.stroke = 0x000000; bestScoreText.strokeThickness = 3; bestScoreText.visible = false; LK.gui.center.addChild(bestScoreText); bestScoreText.y = -50; // Create retry button with enhanced styling var retryButton = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 380, height: 110, alpha: 1.0 }); retryButton.tint = 0xFF9800; // Orange like original Flappy Bird retryButton.visible = false; LK.gui.center.addChild(retryButton); retryButton.y = 100; // Add retry button shadow for depth var retryButtonShadow = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 380, height: 110, alpha: 0.3 }); retryButtonShadow.tint = 0xE65100; // Darker orange shadow retryButtonShadow.visible = false; LK.gui.center.addChild(retryButtonShadow); retryButtonShadow.y = 108; // Offset shadow slightly down retryButtonShadow.x = 4; // Offset shadow slightly right // Add retry button highlight var retryButtonHighlight = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 350, height: 85, alpha: 0.4 }); retryButtonHighlight.tint = 0xFFB74D; // Lighter orange highlight retryButtonHighlight.visible = false; LK.gui.center.addChild(retryButtonHighlight); retryButtonHighlight.y = 92; // Offset highlight slightly up var retryButtonText = new Text2('TEKRAR DENE', { size: 44, fill: 0xFFFFFF }); retryButtonText.anchor.set(0.5, 0.5); retryButtonText.stroke = 0xE65100; retryButtonText.strokeThickness = 3; retryButtonText.visible = false; LK.gui.center.addChild(retryButtonText); retryButtonText.y = 100; // Create menu button with enhanced styling var menuButton = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 380, height: 110, alpha: 1.0 }); menuButton.tint = 0xF44336; // Red like original Flappy Bird menuButton.visible = false; LK.gui.center.addChild(menuButton); menuButton.y = 250; // Add menu button shadow for depth var menuButtonShadow = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 380, height: 110, alpha: 0.3 }); menuButtonShadow.tint = 0xD32F2F; // Darker red shadow menuButtonShadow.visible = false; LK.gui.center.addChild(menuButtonShadow); menuButtonShadow.y = 258; // Offset shadow slightly down menuButtonShadow.x = 4; // Offset shadow slightly right // Add menu button highlight var menuButtonHighlight = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 350, height: 85, alpha: 0.4 }); menuButtonHighlight.tint = 0xEF5350; // Lighter red highlight menuButtonHighlight.visible = false; LK.gui.center.addChild(menuButtonHighlight); menuButtonHighlight.y = 242; // Offset highlight slightly up var menuButtonText = new Text2('ANA MENÜ', { size: 44, fill: 0xFFFFFF }); menuButtonText.anchor.set(0.5, 0.5); menuButtonText.stroke = 0xD32F2F; menuButtonText.strokeThickness = 3; menuButtonText.visible = false; LK.gui.center.addChild(menuButtonText); menuButtonText.y = 250; // Create separate settings button element var settingsButton = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 100, alpha: 1.0 }); settingsButton.tint = 0x8E44AD; try { if (LK.gui && LK.gui.topRight) { LK.gui.topRight.addChild(settingsButton); settingsButton.x = -80; settingsButton.y = 80; } } catch (e) { console.log("Settings button error:", e); } // Create separate settings button shadow element var settingsButtonShadow = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 100, height: 100, alpha: 0.3 }); settingsButtonShadow.tint = 0x6B2C91; // Darker purple shadow try { if (LK.gui && LK.gui.topRight) { LK.gui.topRight.addChild(settingsButtonShadow); settingsButtonShadow.x = -77; settingsButtonShadow.y = 83; } } catch (e) { console.log("Settings button shadow error:", e); } // Create separate settings button highlight element var settingsButtonHighlight = LK.getAsset('playButtonOval', { anchorX: 0.5, anchorY: 0.5, width: 85, height: 85, alpha: 0.4 }); settingsButtonHighlight.tint = 0xBB8FCE; // Lighter purple highlight try { if (LK.gui && LK.gui.topRight) { LK.gui.topRight.addChild(settingsButtonHighlight); settingsButtonHighlight.x = -80; settingsButtonHighlight.y = 77; } } catch (e) { console.log("Settings button highlight error:", e); } // Create separate settings icon text element var settingsIcon = new Text2('⚙', { size: 60, fill: 0xFFFFFF }); settingsIcon.anchor.set(0.5, 0.5); settingsIcon.stroke = 0x6B2C91; settingsIcon.strokeThickness = 2; try { if (LK.gui && LK.gui.topRight) { LK.gui.topRight.addChild(settingsIcon); settingsIcon.x = -80; settingsIcon.y = 80; } } catch (e) { console.log("Settings icon error:", e); } // Create settings menu overlay (initially hidden) var settingsOverlay = LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 1.0 }); settingsOverlay.tint = 0x2F4F4F; settingsOverlay.visible = false; LK.gui.center.addChild(settingsOverlay); var settingsTitle = new Text2('AYARLAR', { size: 100, fill: 0xFFFFFF }); settingsTitle.anchor.set(0.5, 0.5); settingsTitle.stroke = 0x000000; settingsTitle.strokeThickness = 5; settingsTitle.visible = false; LK.gui.center.addChild(settingsTitle); settingsTitle.y = -300; // Create close settings button with modern rectangular design var closeSettingsButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 70, alpha: 1.0 }); closeSettingsButton.tint = 0x95A5A6; closeSettingsButton.visible = false; LK.gui.center.addChild(closeSettingsButton); closeSettingsButton.y = 150; // Add close button shadow for depth var closeSettingsButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 70, alpha: 0.3 }); closeSettingsButtonShadow.tint = 0x7F8C8D; closeSettingsButtonShadow.visible = false; LK.gui.center.addChild(closeSettingsButtonShadow); closeSettingsButtonShadow.y = 155; closeSettingsButtonShadow.x = 3; // Add close button highlight var closeSettingsButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 55, alpha: 0.4 }); closeSettingsButtonHighlight.tint = 0xBDC3C7; closeSettingsButtonHighlight.visible = false; LK.gui.center.addChild(closeSettingsButtonHighlight); closeSettingsButtonHighlight.y = 145; var closeSettingsText = new Text2('KAPAT', { size: 36, fill: 0xFFFFFF }); closeSettingsText.anchor.set(0.5, 0.5); closeSettingsText.stroke = 0x7F8C8D; closeSettingsText.strokeThickness = 2; closeSettingsText.visible = false; LK.gui.center.addChild(closeSettingsText); closeSettingsText.y = 150; // Create speed menu button with modern rectangular design var speedMenuButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 340, height: 75, alpha: 1.0 }); speedMenuButton.tint = 0x3498DB; speedMenuButton.visible = false; LK.gui.center.addChild(speedMenuButton); speedMenuButton.y = -150; // Add speed button shadow for depth var speedMenuButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 340, height: 75, alpha: 0.3 }); speedMenuButtonShadow.tint = 0x2980B9; speedMenuButtonShadow.visible = false; LK.gui.center.addChild(speedMenuButtonShadow); speedMenuButtonShadow.y = -145; speedMenuButtonShadow.x = 3; // Add speed button highlight var speedMenuButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 320, height: 60, alpha: 0.4 }); speedMenuButtonHighlight.tint = 0x5DADE2; speedMenuButtonHighlight.visible = false; LK.gui.center.addChild(speedMenuButtonHighlight); speedMenuButtonHighlight.y = -155; var speedMenuText = new Text2('HIZ', { size: 42, fill: 0xFFFFFF }); speedMenuText.anchor.set(0.5, 0.5); speedMenuText.stroke = 0x2980B9; speedMenuText.strokeThickness = 2; speedMenuText.visible = false; LK.gui.center.addChild(speedMenuText); speedMenuText.y = -150; // Create language menu button with modern rectangular design var languageMenuButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 340, height: 75, alpha: 1.0 }); languageMenuButton.tint = 0x9B59B6; languageMenuButton.visible = false; LK.gui.center.addChild(languageMenuButton); languageMenuButton.y = -20; // Add language button shadow for depth var languageMenuButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 340, height: 75, alpha: 0.3 }); languageMenuButtonShadow.tint = 0x8E44AD; languageMenuButtonShadow.visible = false; LK.gui.center.addChild(languageMenuButtonShadow); languageMenuButtonShadow.y = -15; languageMenuButtonShadow.x = 3; // Add language button highlight var languageMenuButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 320, height: 60, alpha: 0.4 }); languageMenuButtonHighlight.tint = 0xBB8FCE; languageMenuButtonHighlight.visible = false; LK.gui.center.addChild(languageMenuButtonHighlight); languageMenuButtonHighlight.y = -25; var languageMenuText = new Text2('DİL', { size: 42, fill: 0xFFFFFF }); languageMenuText.anchor.set(0.5, 0.5); languageMenuText.stroke = 0x8E44AD; languageMenuText.strokeThickness = 2; languageMenuText.visible = false; LK.gui.center.addChild(languageMenuText); languageMenuText.y = -20; // Create new speed control elements var speedTitle = new Text2('HIZ AYARI', { size: 80, fill: 0xFFFFFF }); speedTitle.anchor.set(0.5, 0.5); speedTitle.stroke = 0x000000; speedTitle.strokeThickness = 4; speedTitle.visible = false; LK.gui.center.addChild(speedTitle); speedTitle.y = -200; // Create speed option buttons with modern rectangular design var normalSpeedButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 1.0 }); normalSpeedButton.tint = 0x27AE60; normalSpeedButton.visible = false; LK.gui.center.addChild(normalSpeedButton); normalSpeedButton.y = -80; normalSpeedButton.x = -280; // Add normal speed button shadow var normalSpeedButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 0.3 }); normalSpeedButtonShadow.tint = 0x1E8449; normalSpeedButtonShadow.visible = false; LK.gui.center.addChild(normalSpeedButtonShadow); normalSpeedButtonShadow.y = -75; normalSpeedButtonShadow.x = -277; // Add normal speed button highlight var normalSpeedButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 160, height: 50, alpha: 0.4 }); normalSpeedButtonHighlight.tint = 0x58D68D; normalSpeedButtonHighlight.visible = false; LK.gui.center.addChild(normalSpeedButtonHighlight); normalSpeedButtonHighlight.y = -85; normalSpeedButtonHighlight.x = -280; var normalSpeedText = new Text2('NORMAL', { size: 32, fill: 0xFFFFFF }); normalSpeedText.anchor.set(0.5, 0.5); normalSpeedText.stroke = 0x1E8449; normalSpeedText.strokeThickness = 2; normalSpeedText.visible = false; LK.gui.center.addChild(normalSpeedText); normalSpeedText.y = -80; normalSpeedText.x = -280; var speed15xButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 1.0 }); speed15xButton.tint = 0xF39C12; speed15xButton.visible = false; LK.gui.center.addChild(speed15xButton); speed15xButton.y = -80; speed15xButton.x = 0; // Add 1.5x speed button shadow var speed15xButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 0.3 }); speed15xButtonShadow.tint = 0xD68910; speed15xButtonShadow.visible = false; LK.gui.center.addChild(speed15xButtonShadow); speed15xButtonShadow.y = -75; speed15xButtonShadow.x = 3; // Add 1.5x speed button highlight var speed15xButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 160, height: 50, alpha: 0.4 }); speed15xButtonHighlight.tint = 0xF7DC6F; speed15xButtonHighlight.visible = false; LK.gui.center.addChild(speed15xButtonHighlight); speed15xButtonHighlight.y = -85; speed15xButtonHighlight.x = 0; var speed15xText = new Text2('1.5X', { size: 32, fill: 0xFFFFFF }); speed15xText.anchor.set(0.5, 0.5); speed15xText.stroke = 0xD68910; speed15xText.strokeThickness = 2; speed15xText.visible = false; LK.gui.center.addChild(speed15xText); speed15xText.y = -80; speed15xText.x = 0; var speed2xButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 1.0 }); speed2xButton.tint = 0xE74C3C; speed2xButton.visible = false; LK.gui.center.addChild(speed2xButton); speed2xButton.y = -80; speed2xButton.x = 180; // Add 2x speed button shadow var speed2xButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 0.3 }); speed2xButtonShadow.tint = 0xC0392B; speed2xButtonShadow.visible = false; LK.gui.center.addChild(speed2xButtonShadow); speed2xButtonShadow.y = -75; speed2xButtonShadow.x = 183; // Add 2x speed button highlight var speed2xButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 160, height: 50, alpha: 0.4 }); speed2xButtonHighlight.tint = 0xF1948A; speed2xButtonHighlight.visible = false; LK.gui.center.addChild(speed2xButtonHighlight); speed2xButtonHighlight.y = -85; speed2xButtonHighlight.x = 180; var speed2xText = new Text2('2X', { size: 32, fill: 0xFFFFFF }); speed2xText.anchor.set(0.5, 0.5); speed2xText.stroke = 0xC0392B; speed2xText.strokeThickness = 2; speed2xText.visible = false; LK.gui.center.addChild(speed2xText); speed2xText.y = -80; speed2xText.x = 180; // Create 2.5x speed button var speed25xButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 1.0 }); speed25xButton.tint = 0x9C27B0; speed25xButton.visible = false; LK.gui.center.addChild(speed25xButton); speed25xButton.y = -80; speed25xButton.x = 360; // Add 2.5x speed button shadow var speed25xButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 180, height: 65, alpha: 0.3 }); speed25xButtonShadow.tint = 0x7B1FA2; speed25xButtonShadow.visible = false; LK.gui.center.addChild(speed25xButtonShadow); speed25xButtonShadow.y = -75; speed25xButtonShadow.x = 363; // Add 2.5x speed button highlight var speed25xButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 160, height: 50, alpha: 0.4 }); speed25xButtonHighlight.tint = 0xBA68C8; speed25xButtonHighlight.visible = false; LK.gui.center.addChild(speed25xButtonHighlight); speed25xButtonHighlight.y = -85; speed25xButtonHighlight.x = 360; var speed25xText = new Text2('2.5X', { size: 32, fill: 0xFFFFFF }); speed25xText.anchor.set(0.5, 0.5); speed25xText.stroke = 0x7B1FA2; speed25xText.strokeThickness = 2; speed25xText.visible = false; LK.gui.center.addChild(speed25xText); speed25xText.y = -80; speed25xText.x = 360; // Current speed indicator var currentSpeedText = new Text2('MEVCUT: NORMAL', { size: 50, fill: 0xFFD700 }); currentSpeedText.anchor.set(0.5, 0.5); currentSpeedText.stroke = 0x000000; currentSpeedText.strokeThickness = 3; currentSpeedText.visible = false; LK.gui.center.addChild(currentSpeedText); currentSpeedText.y = 30; // Create back button for speed controls with modern rectangular design var speedBackButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 65, alpha: 1.0 }); speedBackButton.tint = 0x7F8C8D; speedBackButton.visible = false; LK.gui.center.addChild(speedBackButton); speedBackButton.y = 150; // Add speed back button shadow var speedBackButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 65, alpha: 0.3 }); speedBackButtonShadow.tint = 0x566573; speedBackButtonShadow.visible = false; LK.gui.center.addChild(speedBackButtonShadow); speedBackButtonShadow.y = 155; speedBackButtonShadow.x = 3; // Add speed back button highlight var speedBackButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 50, alpha: 0.4 }); speedBackButtonHighlight.tint = 0xABB2B9; speedBackButtonHighlight.visible = false; LK.gui.center.addChild(speedBackButtonHighlight); speedBackButtonHighlight.y = 145; var speedBackText = new Text2('GERİ', { size: 36, fill: 0xFFFFFF }); speedBackText.anchor.set(0.5, 0.5); speedBackText.stroke = 0x566573; speedBackText.strokeThickness = 2; speedBackText.visible = false; LK.gui.center.addChild(speedBackText); speedBackText.y = 150; // Create invisible barrier blocks to constrain bird before game starts var topBarrier = game.addChild(LK.getAsset('barrier', { anchorX: 0.5, anchorY: 1 })); topBarrier.x = 400; topBarrier.y = 1316; // 50 pixels above bird topBarrier.alpha = 0; // Make invisible var bottomBarrier = game.addChild(LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0 })); bottomBarrier.x = 400; bottomBarrier.y = 1416; // 50 pixels below bird bottomBarrier.alpha = 0; // Make invisible // Create and add background image (appears behind barriers but in front of other elements) var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0 })); background.x = 0; background.y = 0; // Scale background to fill screen for better performance background.scaleX = 2; background.scaleY = 2; // Create ground ground = game.addChild(LK.getAsset('ground', { anchorX: 0, anchorY: 1 })); ground.x = 0; ground.y = 2732; ground.tint = 0x654321; // Create bird bird = game.addChild(new Bird()); bird.x = 400; bird.y = 1366; // Initialize bird properly bird.velocity = 0; // Create pipe function function createPipe() { // Define safe boundaries for gap center to ensure both pipes have reasonable heights var minGapY = 700; // Increased minimum gap center position for better clearance var maxGapY = 1900; // Adjusted maximum gap center position for better clearance var gapCenterY; // Create more varied random patterns with better distribution var randomPattern = Math.random(); if (randomPattern < 0.4) { // 40% chance for high gaps (easier to navigate) gapCenterY = minGapY + Math.random() * 300; } else if (randomPattern < 0.7) { // 30% chance for middle gaps (moderate difficulty) gapCenterY = 1000 + Math.random() * 500; } else { // 30% chance for low gaps (more challenging but still passable) gapCenterY = maxGapY - Math.random() * 300; } // Add some variation based on current score for progressive difficulty var currentScore = LK.getScore(); if (currentScore > 10) { // After score 10, make gaps slightly more challenging var difficultyFactor = Math.min(0.8, currentScore / 50); // Max 80% difficulty increase var centerPull = 1300; // Pull towards center-high area gapCenterY = gapCenterY + (centerPull - gapCenterY) * difficultyFactor * 0.3; } // Ensure the gap stays within safe boundaries gapCenterY = Math.max(minGapY, Math.min(maxGapY, gapCenterY)); var pipe = new Pipe(gapCenterY); // Calculate position based on last pipe position + consistent spacing if (pipes.length === 0) { pipe.x = 2048 + 100; // First pipe position - brought closer } else { pipe.x = pipes[pipes.length - 1].x + pipeSpacing; // Consistent spacing from last pipe } ; pipes.push(pipe); game.addChild(pipe); } // Reset game function function resetGame() { // Reset bird bird.x = 400; bird.y = 1366; bird.velocity = 0; // Clear pipes for (var i = pipes.length - 1; i >= 0; i--) { pipes[i].destroy(); } pipes = []; // Reset variables gameStarted = false; gameOver = false; showMainMenu = true; showGameOver = false; // Hide game over screen hideGameOverScreen(); LK.setScore(0); scoreTxt.setText('0'); // Show main menu mainMenuTitle.visible = true; // Show play button elements if (playButton) playButton.visible = true; if (playButtonShadow) playButtonShadow.visible = true; if (playButtonHighlight) playButtonHighlight.visible = true; if (playButtonText) playButtonText.visible = true; // Start play button animation startPlayButtonAnimation(); // Show all settings button elements settingsButton.visible = true; settingsButtonShadow.visible = true; settingsButtonHighlight.visible = true; settingsIcon.visible = true; // Show cup shape (high score indicator) if (cupShape) cupShape.visible = true; // Hide instruction instructionTxt.visible = false; // Clear existing barriers if they exist if (topBarrier) { topBarrier.destroy(); topBarrier = null; } if (bottomBarrier) { bottomBarrier.destroy(); bottomBarrier = null; } // Recreate invisible barriers topBarrier = game.addChild(LK.getAsset('barrier', { anchorX: 0.5, anchorY: 1 })); topBarrier.x = 400; topBarrier.y = 1316; // 50 pixels above bird topBarrier.alpha = 0; // Make invisible bottomBarrier = game.addChild(LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0 })); bottomBarrier.x = 400; bottomBarrier.y = 1416; // 50 pixels below bird bottomBarrier.alpha = 0; // Make invisible // Create initial pipes createPipe(); createPipe(); } // Function to start game from main menu function startGameFromMenu() { showMainMenu = false; // Hide main menu elements mainMenuTitle.visible = false; // Hide play button elements if (playButton) playButton.visible = false; if (playButtonShadow) playButtonShadow.visible = false; if (playButtonHighlight) playButtonHighlight.visible = false; if (playButtonText) playButtonText.visible = false; // Hide all settings button elements settingsButton.visible = false; settingsButtonShadow.visible = false; settingsButtonHighlight.visible = false; settingsIcon.visible = false; // Hide cup shape (high score indicator) if (cupShape) cupShape.visible = false; // Show instruction instructionTxt.visible = true; } // Function to show game over screen function showGameOverScreen(finalScore) { showGameOver = true; gameStarted = false; showMainMenu = false; // Hide instruction instructionTxt.visible = false; // Show game over elements gameOverBg.visible = true; gameOverTitle.visible = true; finalScoreText.visible = true; bestScoreText.visible = true; retryButton.visible = true; retryButtonText.visible = true; retryButtonShadow.visible = true; retryButtonHighlight.visible = true; menuButton.visible = true; menuButtonText.visible = true; menuButtonShadow.visible = true; menuButtonHighlight.visible = true; // Update score displays finalScoreText.setText(getText('score') + ': ' + finalScore); // Use proper text sizing if (finalScoreText.width > 600) { var newSize = Math.max(50, Math.floor(80 * 600 / finalScoreText.width)); finalScoreText.style = { size: newSize, fill: finalScoreText.style.fill }; } // Always show the current high score from storage var currentHighScore = _storage && _storage.highScore ? _storage.highScore : 0; bestScoreText.setText(getText('bestScore') + ': ' + currentHighScore); // Use proper text sizing if (bestScoreText.width > 600) { var newSize = Math.max(40, Math.floor(60 * 600 / bestScoreText.width)); bestScoreText.style = { size: newSize, fill: bestScoreText.style.fill }; } // Add entrance animation for buttons tween(retryButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(retryButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200, easing: tween.easeInOut }); } }); tween(menuButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(menuButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200, easing: tween.easeInOut }); } }); } // Function to hide game over screen function hideGameOverScreen() { showGameOver = false; // Hide game over elements gameOverBg.visible = false; gameOverTitle.visible = false; finalScoreText.visible = false; bestScoreText.visible = false; retryButton.visible = false; retryButtonText.visible = false; retryButtonShadow.visible = false; retryButtonHighlight.visible = false; menuButton.visible = false; menuButtonText.visible = false; menuButtonShadow.visible = false; menuButtonHighlight.visible = false; } // Create speed overlay background - moved to end to ensure it's on top var speedOverlay = LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 1.0 }); speedOverlay.tint = 0x2F4F4F; speedOverlay.visible = false; // Add to front to ensure visibility above all other elements LK.gui.center.addChild(speedOverlay); // Create language overlay background var languageOverlay = LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 1.0 }); languageOverlay.tint = 0x2F4F4F; languageOverlay.visible = false; LK.gui.center.addChild(languageOverlay); // Create language control title var languageTitle = new Text2('DİL SEÇENEKLERİ', { size: 80, fill: 0xFFFFFF }); languageTitle.anchor.set(0.5, 0.5); languageTitle.stroke = 0x000000; languageTitle.strokeThickness = 4; languageTitle.visible = false; LK.gui.center.addChild(languageTitle); languageTitle.y = -200; // Create language option buttons with modern rectangular design var turkishButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 65, alpha: 1.0 }); turkishButton.tint = 0x27AE60; turkishButton.visible = false; LK.gui.center.addChild(turkishButton); turkishButton.y = -80; turkishButton.x = -220; // Add Turkish button shadow var turkishButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 65, alpha: 0.3 }); turkishButtonShadow.tint = 0x1E8449; turkishButtonShadow.visible = false; LK.gui.center.addChild(turkishButtonShadow); turkishButtonShadow.y = -75; turkishButtonShadow.x = -217; // Add Turkish button highlight var turkishButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 50, alpha: 0.4 }); turkishButtonHighlight.tint = 0x58D68D; turkishButtonHighlight.visible = false; LK.gui.center.addChild(turkishButtonHighlight); turkishButtonHighlight.y = -85; turkishButtonHighlight.x = -220; var turkishText = new Text2('TÜRKÇE', { size: 32, fill: 0xFFFFFF }); turkishText.anchor.set(0.5, 0.5); turkishText.stroke = 0x1E8449; turkishText.strokeThickness = 2; turkishText.visible = false; LK.gui.center.addChild(turkishText); turkishText.y = -80; turkishText.x = -220; var englishButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 65, alpha: 1.0 }); englishButton.tint = 0x3498DB; englishButton.visible = false; LK.gui.center.addChild(englishButton); englishButton.y = -80; englishButton.x = 220; // Add English button shadow var englishButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 65, alpha: 0.3 }); englishButtonShadow.tint = 0x2980B9; englishButtonShadow.visible = false; LK.gui.center.addChild(englishButtonShadow); englishButtonShadow.y = -75; englishButtonShadow.x = 223; // Add English button highlight var englishButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 240, height: 50, alpha: 0.4 }); englishButtonHighlight.tint = 0x85C1E9; englishButtonHighlight.visible = false; LK.gui.center.addChild(englishButtonHighlight); englishButtonHighlight.y = -85; englishButtonHighlight.x = 220; var englishText = new Text2('ENGLISH', { size: 32, fill: 0xFFFFFF }); englishText.anchor.set(0.5, 0.5); englishText.stroke = 0x2980B9; englishText.strokeThickness = 2; englishText.visible = false; LK.gui.center.addChild(englishText); englishText.y = -80; englishText.x = 220; // Current language indicator var currentLanguageText = new Text2('MEVCUT: TÜRKÇE', { size: 50, fill: 0xFFD700 }); currentLanguageText.anchor.set(0.5, 0.5); currentLanguageText.stroke = 0x000000; currentLanguageText.strokeThickness = 3; currentLanguageText.visible = false; LK.gui.center.addChild(currentLanguageText); currentLanguageText.y = 30; // Create back button for language controls with modern rectangular design var languageBackButton = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 65, alpha: 1.0 }); languageBackButton.tint = 0x7F8C8D; languageBackButton.visible = false; LK.gui.center.addChild(languageBackButton); languageBackButton.y = 150; // Add language back button shadow var languageBackButtonShadow = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 65, alpha: 0.3 }); languageBackButtonShadow.tint = 0x566573; languageBackButtonShadow.visible = false; LK.gui.center.addChild(languageBackButtonShadow); languageBackButtonShadow.y = 155; languageBackButtonShadow.x = 3; // Add language back button highlight var languageBackButtonHighlight = LK.getAsset('settingsButtonRect', { anchorX: 0.5, anchorY: 0.5, width: 200, height: 50, alpha: 0.4 }); languageBackButtonHighlight.tint = 0xABB2B9; languageBackButtonHighlight.visible = false; LK.gui.center.addChild(languageBackButtonHighlight); languageBackButtonHighlight.y = 145; var languageBackText = new Text2('GERİ', { size: 36, fill: 0xFFFFFF }); languageBackText.anchor.set(0.5, 0.5); languageBackText.stroke = 0x566573; languageBackText.strokeThickness = 2; languageBackText.visible = false; LK.gui.center.addChild(languageBackText); languageBackText.y = 150; // Function to show settings menu function showSettingsMenu() { // Remove and re-add settings overlay to bring it to front LK.gui.center.removeChild(settingsOverlay); LK.gui.center.addChild(settingsOverlay); // Remove and re-add all settings elements to bring them to front LK.gui.center.removeChild(settingsTitle); LK.gui.center.addChild(settingsTitle); LK.gui.center.removeChild(closeSettingsButton); LK.gui.center.addChild(closeSettingsButton); LK.gui.center.removeChild(closeSettingsText); LK.gui.center.addChild(closeSettingsText); LK.gui.center.removeChild(speedMenuButton); LK.gui.center.addChild(speedMenuButton); LK.gui.center.removeChild(speedMenuText); LK.gui.center.addChild(speedMenuText); LK.gui.center.removeChild(languageMenuButton); LK.gui.center.addChild(languageMenuButton); LK.gui.center.removeChild(languageMenuText); LK.gui.center.addChild(languageMenuText); settingsOverlay.visible = true; settingsTitle.visible = true; closeSettingsButton.visible = true; closeSettingsButtonShadow.visible = true; closeSettingsButtonHighlight.visible = true; closeSettingsText.visible = true; speedMenuButton.visible = true; speedMenuButtonShadow.visible = true; speedMenuButtonHighlight.visible = true; speedMenuText.visible = true; languageMenuButton.visible = true; languageMenuButtonShadow.visible = true; languageMenuButtonHighlight.visible = true; languageMenuText.visible = true; } // Function to hide settings menu function hideSettingsMenu() { settingsOverlay.visible = false; settingsTitle.visible = false; closeSettingsButton.visible = false; closeSettingsButtonShadow.visible = false; closeSettingsButtonHighlight.visible = false; closeSettingsText.visible = false; speedMenuButton.visible = false; speedMenuButtonShadow.visible = false; speedMenuButtonHighlight.visible = false; speedMenuText.visible = false; languageMenuButton.visible = false; languageMenuButtonShadow.visible = false; languageMenuButtonHighlight.visible = false; languageMenuText.visible = false; hideSpeedControls(); hideLanguageControls(); } // Function to show language controls function showLanguageControls() { // Hide speed controls first hideSpeedControls(); // Hide language menu button languageMenuButton.visible = false; languageMenuText.visible = false; // Remove and re-add language overlay to bring it to front LK.gui.center.removeChild(languageOverlay); LK.gui.center.addChild(languageOverlay); // Remove and re-add all language elements to bring them to front LK.gui.center.removeChild(languageTitle); LK.gui.center.addChild(languageTitle); LK.gui.center.removeChild(turkishButton); LK.gui.center.addChild(turkishButton); LK.gui.center.removeChild(turkishText); LK.gui.center.addChild(turkishText); LK.gui.center.removeChild(englishButton); LK.gui.center.addChild(englishButton); LK.gui.center.removeChild(englishText); LK.gui.center.addChild(englishText); LK.gui.center.removeChild(currentLanguageText); LK.gui.center.addChild(currentLanguageText); LK.gui.center.removeChild(languageBackButton); LK.gui.center.addChild(languageBackButton); LK.gui.center.removeChild(languageBackText); LK.gui.center.addChild(languageBackText); // Show language overlay and controls languageOverlay.visible = true; languageTitle.visible = true; turkishButton.visible = true; turkishButtonShadow.visible = true; turkishButtonHighlight.visible = true; turkishText.visible = true; englishButton.visible = true; englishButtonShadow.visible = true; englishButtonHighlight.visible = true; englishText.visible = true; currentLanguageText.visible = true; languageBackButton.visible = true; languageBackButtonShadow.visible = true; languageBackButtonHighlight.visible = true; languageBackText.visible = true; updateLanguageDisplay(); } // Function to hide language controls function hideLanguageControls() { languageOverlay.visible = false; languageTitle.visible = false; turkishButton.visible = false; turkishButtonShadow.visible = false; turkishButtonHighlight.visible = false; turkishText.visible = false; englishButton.visible = false; englishButtonShadow.visible = false; englishButtonHighlight.visible = false; englishText.visible = false; currentLanguageText.visible = false; languageBackButton.visible = false; languageBackButtonShadow.visible = false; languageBackButtonHighlight.visible = false; languageBackText.visible = false; // Show language menu button again if settings overlay is visible if (settingsOverlay.visible) { languageMenuButton.visible = true; languageMenuButtonShadow.visible = true; languageMenuButtonHighlight.visible = true; languageMenuText.visible = true; } } // Language text objects var languageTexts = { tr: { mainTitle: 'FLAPPY BIRD', playButton: 'OYNA', instruction: 'TIKLA VE OYNA!', gameOver: 'OYUN BİTTİ', score: 'SKOR', bestScore: 'EN İYİ', retry: 'TEKRAR DENE', mainMenu: 'ANA MENÜ', settings: 'AYARLAR', close: 'KAPAT', speed: 'HIZ', language: 'DİL', speedTitle: 'HIZ AYARI', languageTitle: 'DİL SEÇENEKLERİ', normal: 'NORMAL', current: 'MEVCUT', highestScore: 'EN YÜKSEK', back: 'GERİ' }, en: { mainTitle: 'FLAPPY BIRD', playButton: 'PLAY', instruction: 'CLICK TO PLAY!', gameOver: 'GAME OVER', score: 'SCORE', bestScore: 'BEST', retry: 'RETRY', mainMenu: 'MAIN MENU', settings: 'SETTINGS', close: 'CLOSE', speed: 'SPEED', language: 'LANGUAGE', speedTitle: 'SPEED SETTINGS', languageTitle: 'LANGUAGE OPTIONS', normal: 'NORMAL', current: 'CURRENT', highestScore: 'HIGHEST SCORE', back: 'BACK' } }; // Function to get text for current language function getText(key) { return languageTexts[currentLanguage][key] || languageTexts['en'][key]; } // Function to update all text elements to current language function updateAllTexts() { try { // Main menu texts if (instructionTxt && instructionTxt.setText) { instructionTxt.setText(getText('instruction')); // Use proper text sizing var bgWidth = 400; if (instructionTxt.width > bgWidth - 20) { var newSize = Math.max(40, Math.floor(60 * (bgWidth - 20) / instructionTxt.width)); instructionTxt.style = { size: newSize, fill: instructionTxt.style.fill }; } } // Update play button text if (playButtonText && playButtonText.setText) { playButtonText.setText(getText('playButton')); // Use proper text sizing for play button var playButtonWidth = 370; if (playButtonText.width > playButtonWidth - 20) { var newSize = Math.max(35, Math.floor(50 * (playButtonWidth - 20) / playButtonText.width)); playButtonText.style = { size: newSize, fill: playButtonText.style.fill }; } } // Game over texts - always update these regardless of visibility if (gameOverTitle && gameOverTitle.setText) gameOverTitle.setText(getText('gameOver')); if (retryButtonText && retryButtonText.setText) { retryButtonText.setText(getText('retry')); // Use proper text sizing var retryButtonWidth = 320; if (retryButtonText.width > retryButtonWidth - 20) { var newSize = Math.max(30, Math.floor(38 * (retryButtonWidth - 20) / retryButtonText.width)); retryButtonText.style = { size: newSize, fill: retryButtonText.style.fill }; } } if (menuButtonText && menuButtonText.setText) { menuButtonText.setText(getText('mainMenu')); // Use proper text sizing var menuButtonWidth = 320; if (menuButtonText.width > menuButtonWidth - 20) { var newSize = Math.max(30, Math.floor(38 * (menuButtonWidth - 20) / menuButtonText.width)); menuButtonText.style = { size: newSize, fill: menuButtonText.style.fill }; } } // Settings texts if (settingsTitle && settingsTitle.setText) settingsTitle.setText(getText('settings')); if (closeSettingsText && closeSettingsText.setText) { closeSettingsText.setText(getText('close')); // Use proper text sizing var closeButtonWidth = 240; if (closeSettingsText.width > closeButtonWidth - 20) { var newSize = Math.max(28, Math.floor(36 * (closeButtonWidth - 20) / closeSettingsText.width)); closeSettingsText.style = { size: newSize, fill: closeSettingsText.style.fill }; } } if (speedMenuText && speedMenuText.setText) { speedMenuText.setText(getText('speed')); // Use proper text sizing var speedMenuWidth = 320; if (speedMenuText.width > speedMenuWidth - 20) { var newSize = Math.max(32, Math.floor(42 * (speedMenuWidth - 20) / speedMenuText.width)); speedMenuText.style = { size: newSize, fill: speedMenuText.style.fill }; } } if (languageMenuText && languageMenuText.setText) { languageMenuText.setText(getText('language')); // Use proper text sizing var languageMenuWidth = 320; if (languageMenuText.width > languageMenuWidth - 20) { var newSize = Math.max(32, Math.floor(42 * (languageMenuWidth - 20) / languageMenuText.width)); languageMenuText.style = { size: newSize, fill: languageMenuText.style.fill }; } } if (speedTitle && speedTitle.setText) speedTitle.setText(getText('speedTitle')); if (languageTitle && languageTitle.setText) languageTitle.setText(getText('languageTitle')); if (normalSpeedText && normalSpeedText.setText) { normalSpeedText.setText(getText('normal')); // Use proper text sizing var normalSpeedWidth = 160; if (normalSpeedText.width > normalSpeedWidth - 20) { var newSize = Math.max(24, Math.floor(32 * (normalSpeedWidth - 20) / normalSpeedText.width)); normalSpeedText.style = { size: newSize, fill: normalSpeedText.style.fill }; } } if (speedBackText && speedBackText.setText) { speedBackText.setText(getText('back')); // Use proper text sizing var backButtonWidth = 200; if (speedBackText.width > backButtonWidth - 20) { var newSize = Math.max(28, Math.floor(36 * (backButtonWidth - 20) / speedBackText.width)); speedBackText.style = { size: newSize, fill: speedBackText.style.fill }; } } if (languageBackText && languageBackText.setText) { languageBackText.setText(getText('back')); // Use proper text sizing var langBackButtonWidth = 200; if (languageBackText.width > langBackButtonWidth - 20) { var newSize = Math.max(28, Math.floor(36 * (langBackButtonWidth - 20) / languageBackText.width)); languageBackText.style = { size: newSize, fill: languageBackText.style.fill }; } } // Update current speed text with proper language var speedText = getText('normal'); if (gameSpeed === 2) speedText = '2X';else if (gameSpeed === 1.5) speedText = '1.5X';else if (gameSpeed === 2.5) speedText = '2.5X'; if (currentSpeedText && currentSpeedText.setText) { currentSpeedText.setText(getText('current') + ': ' + speedText); // Use proper text sizing if (currentSpeedText.width > 600) { var newSize = Math.max(35, Math.floor(50 * 600 / currentSpeedText.width)); currentSpeedText.style = { size: newSize, fill: currentSpeedText.style.fill }; } } // Update final and best score texts - always update these regardless of visibility if (finalScoreText && finalScoreText.setText) { var currentScore = LK.getScore(); finalScoreText.setText(getText('score') + ': ' + currentScore); if (finalScoreText.width > 600) { var newSize = Math.max(50, Math.floor(80 * 600 / finalScoreText.width)); finalScoreText.style = { size: newSize, fill: finalScoreText.style.fill }; } } if (bestScoreText && bestScoreText.setText) { var currentHighScore = _storage.highScore || 0; bestScoreText.setText(getText('bestScore') + ': ' + currentHighScore); if (bestScoreText.width > 600) { var newSize = Math.max(40, Math.floor(60 * 600 / bestScoreText.width)); bestScoreText.style = { size: newSize, fill: bestScoreText.style.fill }; } } } catch (e) { console.log("Text update error:", e); } } // Function to update language display function updateLanguageDisplay() { var langText = currentLanguage === 'tr' ? 'TÜRKÇE' : 'ENGLISH'; var currentText = currentLanguage === 'tr' ? 'MEVCUT' : 'CURRENT'; currentLanguageText.setText(currentText + ': ' + langText); // Use proper text sizing if (currentLanguageText.width > 600) { var newSize = Math.max(35, Math.floor(50 * 600 / currentLanguageText.width)); currentLanguageText.style = { size: newSize, fill: currentLanguageText.style.fill }; } // Update button colors to show selected language turkishButton.tint = currentLanguage === 'tr' ? 0x2ECC71 : 0x27AE60; englishButton.tint = currentLanguage === 'en' ? 0x5DADE2 : 0x3498DB; // Ensure language button texts fit properly if (turkishText && turkishText.setText) { turkishText.setText('TÜRKÇE'); var turkishButtonWidth = 240; if (turkishText.width > turkishButtonWidth - 20) { var newSize = Math.max(24, Math.floor(32 * (turkishButtonWidth - 20) / turkishText.width)); turkishText.style = { size: newSize, fill: turkishText.style.fill }; } } if (englishText && englishText.setText) { englishText.setText('ENGLISH'); var englishButtonWidth = 240; if (englishText.width > englishButtonWidth - 20) { var newSize = Math.max(24, Math.floor(32 * (englishButtonWidth - 20) / englishText.width)); englishText.style = { size: newSize, fill: englishText.style.fill }; } } } // Function to set language function setLanguage(lang) { currentLanguage = lang; _storage.language = lang; // Update all text elements immediately updateAllTexts(); // Update language display updateLanguageDisplay(); // Update speed display to use correct language updateSpeedDisplay(); } // Function to show speed controls function showSpeedControls() { // Hide language controls first hideLanguageControls(); // Hide speed menu button speedMenuButton.visible = false; speedMenuText.visible = false; // Remove and re-add speed overlay to bring it to front LK.gui.center.removeChild(speedOverlay); LK.gui.center.addChild(speedOverlay); // Remove and re-add all speed elements to bring them to front LK.gui.center.removeChild(speedTitle); LK.gui.center.addChild(speedTitle); LK.gui.center.removeChild(normalSpeedButton); LK.gui.center.addChild(normalSpeedButton); LK.gui.center.removeChild(normalSpeedText); LK.gui.center.addChild(normalSpeedText); LK.gui.center.removeChild(speed15xButton); LK.gui.center.addChild(speed15xButton); LK.gui.center.removeChild(speed15xText); LK.gui.center.addChild(speed15xText); LK.gui.center.removeChild(speed2xButton); LK.gui.center.addChild(speed2xButton); LK.gui.center.removeChild(speed2xText); LK.gui.center.addChild(speed2xText); LK.gui.center.removeChild(speed25xButton); LK.gui.center.addChild(speed25xButton); LK.gui.center.removeChild(speed25xText); LK.gui.center.addChild(speed25xText); LK.gui.center.removeChild(currentSpeedText); LK.gui.center.addChild(currentSpeedText); LK.gui.center.removeChild(speedBackButton); LK.gui.center.addChild(speedBackButton); LK.gui.center.removeChild(speedBackText); LK.gui.center.addChild(speedBackText); // Show speed overlay and controls speedOverlay.visible = true; speedTitle.visible = true; normalSpeedButton.visible = true; normalSpeedButtonShadow.visible = true; normalSpeedButtonHighlight.visible = true; normalSpeedText.visible = true; speed15xButton.visible = true; speed15xButtonShadow.visible = true; speed15xButtonHighlight.visible = true; speed15xText.visible = true; speed2xButton.visible = true; speed2xButtonShadow.visible = true; speed2xButtonHighlight.visible = true; speed2xText.visible = true; speed25xButton.visible = true; speed25xButtonShadow.visible = true; speed25xButtonHighlight.visible = true; speed25xText.visible = true; currentSpeedText.visible = true; speedBackButton.visible = true; speedBackButtonShadow.visible = true; speedBackButtonHighlight.visible = true; speedBackText.visible = true; updateSpeedDisplay(); } // Function to hide speed controls function hideSpeedControls() { speedOverlay.visible = false; speedTitle.visible = false; normalSpeedButton.visible = false; normalSpeedButtonShadow.visible = false; normalSpeedButtonHighlight.visible = false; normalSpeedText.visible = false; speed2xButton.visible = false; speed2xButtonShadow.visible = false; speed2xButtonHighlight.visible = false; speed2xText.visible = false; speed25xButton.visible = false; speed25xButtonShadow.visible = false; speed25xButtonHighlight.visible = false; speed25xText.visible = false; speed15xButton.visible = false; speed15xButtonShadow.visible = false; speed15xButtonHighlight.visible = false; speed15xText.visible = false; currentSpeedText.visible = false; speedBackButton.visible = false; speedBackButtonShadow.visible = false; speedBackButtonHighlight.visible = false; speedBackText.visible = false; // Show speed menu button again if settings overlay is visible if (settingsOverlay.visible) { speedMenuButton.visible = true; speedMenuButtonShadow.visible = true; speedMenuButtonHighlight.visible = true; speedMenuText.visible = true; } } // Function to update speed display function updateSpeedDisplay() { var speedText = getText('normal'); if (gameSpeed === 2) speedText = '2X';else if (gameSpeed === 1.5) speedText = '1.5X';else if (gameSpeed === 2.5) speedText = '2.5X'; currentSpeedText.setText(getText('current') + ': ' + speedText); // Use proper text sizing if (currentSpeedText.width > 600) { var newSize = Math.max(35, Math.floor(50 * 600 / currentSpeedText.width)); currentSpeedText.style = { size: newSize, fill: currentSpeedText.style.fill }; } // Update button colors to show selected speed with more distinct colors normalSpeedButton.tint = gameSpeed === 1 ? 0x1ABC9C : 0x27AE60; // Brighter teal when selected speed2xButton.tint = gameSpeed === 2 ? 0xFF6B6B : 0xE74C3C; // Brighter red when selected speed15xButton.tint = gameSpeed === 1.5 ? 0xFFE066 : 0xF39C12; // Brighter yellow when selected speed25xButton.tint = gameSpeed === 2.5 ? 0xE91E63 : 0x9C27B0; // Brighter purple when selected // Add subtle pulse animation to the selected button if (gameSpeed === 1) { tween(normalSpeedButton, { scaleX: 1.05, scaleY: 1.05 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(normalSpeedButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 500, easing: tween.easeInOut }); } }); } else if (gameSpeed === 1.5) { tween(speed15xButton, { scaleX: 1.05, scaleY: 1.05 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(speed15xButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 500, easing: tween.easeInOut }); } }); } else if (gameSpeed === 2) { tween(speed2xButton, { scaleX: 1.05, scaleY: 1.05 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(speed2xButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 500, easing: tween.easeInOut }); } }); } else if (gameSpeed === 2.5) { tween(speed25xButton, { scaleX: 1.05, scaleY: 1.05 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(speed25xButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 500, easing: tween.easeInOut }); } }); } // Ensure speed button texts fit properly and use correct language if (normalSpeedText && normalSpeedText.setText) { normalSpeedText.setText(getText('normal')); var normalButtonWidth = 160; if (normalSpeedText.width > normalButtonWidth - 20) { var newSize = Math.max(24, Math.floor(32 * (normalButtonWidth - 20) / normalSpeedText.width)); normalSpeedText.style = { size: newSize, fill: normalSpeedText.style.fill }; } } } // Function to set game speed function setGameSpeed(newSpeed) { gameSpeed = newSpeed; // Update dynamic spacing based on new speed pipeSpacing = 500 + gameSpeed * 50; updateSpeedDisplay(); // Update existing pipes if they exist for (var i = 0; i < pipes.length; i++) { if (pipes[i]) { pipes[i].speed = basePipeSpeed * gameSpeed; // Update gap size for existing pipes pipes[i].gapSize = 750 + (gameSpeed - 1) * 50; } } } // Current language variable var currentLanguage = 'tr'; // Default to Turkish // Initialize local storage arrays if they don't exist try { // Use persistent storage directly _storage = storage; // Initialize arrays and values if they don't exist, but preserve existing values if (!_storage.globalLeaderboardNames) _storage.globalLeaderboardNames = []; if (!_storage.globalLeaderboardScores) _storage.globalLeaderboardScores = []; if (typeof _storage.highScore === 'undefined') _storage.highScore = 0; if (typeof _storage.lastScore === 'undefined') _storage.lastScore = 0; if (!_storage.language) _storage.language = 'tr'; if (!_storage.username) _storage.username = 'Oyuncu1'; currentLanguage = _storage.language; } catch (e) { console.log("Storage initialization error:", e); _storage = { globalLeaderboardNames: [], globalLeaderboardScores: [], highScore: 0, lastScore: 0, language: 'tr', username: 'Oyuncu1' }; } // Initialize username if not exists if (!_storage.username) { var playerNumber = 1; while (_storage.globalLeaderboardNames.indexOf('Oyuncu ' + playerNumber) !== -1) { playerNumber++; } _storage.username = 'Oyuncu ' + playerNumber; } // Create animated play button for main menu var playButton = LK.getAsset('playButtonMain', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 120, alpha: 1.0 }); playButton.tint = 0xFF9800; // Flappy Bird orange try { if (LK.gui && LK.gui.center) { LK.gui.center.addChild(playButton); playButton.y = -100; } } catch (e) { console.log("Play button error:", e); } // Create separate play button shadow element var playButtonShadow = LK.getAsset('playButtonShadow', { anchorX: 0.5, anchorY: 0.5, width: 400, height: 120, alpha: 0.4 }); playButtonShadow.tint = 0xE65100; // Darker orange shadow try { if (LK.gui && LK.gui.center) { LK.gui.center.addChild(playButtonShadow); playButtonShadow.y = -92; // Offset shadow slightly up playButtonShadow.x = 4; // Offset shadow slightly right } } catch (e) { console.log("Play button shadow error:", e); } // Create separate play button highlight element var playButtonHighlight = LK.getAsset('playButtonHighlight', { anchorX: 0.5, anchorY: 0.5, width: 370, height: 95, alpha: 0.5 }); playButtonHighlight.tint = 0xFFB74D; // Lighter orange highlight try { if (LK.gui && LK.gui.center) { LK.gui.center.addChild(playButtonHighlight); playButtonHighlight.y = -108; // Offset highlight slightly down } } catch (e) { console.log("Play button highlight error:", e); } // Create separate play button text element var playButtonText = new Text2('OYNA', { size: 50, fill: 0xFFFFFF }); playButtonText.anchor.set(0.5, 0.5); playButtonText.stroke = 0xE65100; playButtonText.strokeThickness = 4; try { if (LK.gui && LK.gui.center) { LK.gui.center.addChild(playButtonText); playButtonText.y = -100; } } catch (e) { console.log("Play button text error:", e); } // Start continuous floating animation for play button function startPlayButtonAnimation() { if (playButton && playButton.parent) { tween(playButton, { y: -120, scaleX: 1.05, scaleY: 1.05 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (playButton && playButton.parent) { tween(playButton, { y: -80, scaleX: 0.95, scaleY: 0.95 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (showMainMenu) { startPlayButtonAnimation(); // Loop animation } } }); } } }); } // Animate shadow with slight delay if (playButtonShadow && playButtonShadow.parent) { tween(playButtonShadow, { y: -112, scaleX: 1.05, scaleY: 1.05, alpha: 0.3 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (playButtonShadow && playButtonShadow.parent) { tween(playButtonShadow, { y: -72, scaleX: 0.95, scaleY: 0.95, alpha: 0.4 }, { duration: 1500, easing: tween.easeInOut }); } } }); } // Animate highlight with slight delay if (playButtonHighlight && playButtonHighlight.parent) { tween(playButtonHighlight, { y: -128, scaleX: 1.05, scaleY: 1.05, alpha: 0.4 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (playButtonHighlight && playButtonHighlight.parent) { tween(playButtonHighlight, { y: -88, scaleX: 0.95, scaleY: 0.95, alpha: 0.5 }, { duration: 1500, easing: tween.easeInOut }); } } }); } // Animate text if (playButtonText && playButtonText.parent) { tween(playButtonText, { y: -120, scaleX: 1.05, scaleY: 1.05 }, { duration: 1500, easing: tween.easeInOut, onFinish: function onFinish() { if (playButtonText && playButtonText.parent) { tween(playButtonText, { y: -80, scaleX: 0.95, scaleY: 0.95 }, { duration: 1500, easing: tween.easeInOut }); } } }); } } // Initialize game resetGame(); // Use resetGame to properly initialize all states // Update all texts to current language updateAllTexts(); // Touch/click handler game.down = function (x, y, obj) { // Check settings button click - settings button is positioned at topRight with offset var settingsX = 2048 - 80; // topRight.x + settingsButton.x offset var settingsY = 80; // topRight.y + settingsButton.y offset var settingsSize = 120; // Settings button size if (x >= settingsX - settingsSize / 2 && x <= settingsX + settingsSize / 2 && y >= settingsY - settingsSize / 2 && y <= settingsY + settingsSize / 2) { // Prevent rapid clicks var currentTime; try { currentTime = Date.now ? Date.now() : new Date().getTime(); } catch (e) { currentTime = 0; } if (currentTime - lastButtonClickTime < 500) { return; // Ignore click if too recent } lastButtonClickTime = currentTime; // Add visual feedback with tween for all settings button elements tween(settingsButton, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(settingsButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); // Animate settings button shadow tween(settingsButtonShadow, { scaleX: 1.2, scaleY: 1.2, alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(settingsButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 100 }); } }); // Animate settings button highlight tween(settingsButtonHighlight, { scaleX: 1.2, scaleY: 1.2, alpha: 0.6 }, { duration: 100, onFinish: function onFinish() { tween(settingsButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 100 }); } }); // Animate settings icon tween(settingsIcon, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(settingsIcon, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); showSettingsMenu(); return; } // Check close settings button if settings menu is open if (settingsOverlay.visible) { // Add invisible barriers between menu sections to prevent overlapping clicks // Speed menu section barrier (between speed and language menus) if (speedMenuButton.visible && !speedOverlay.visible && !languageOverlay.visible) { // Check speed menu button (HIZ) with isolated click area if (x >= 824 && x <= 1224 && y >= 1166 && y <= 1266) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(speedMenuButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(speedMenuButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); // Animate shadow and highlight for depth effect tween(speedMenuButtonShadow, { scaleX: 1.1, scaleY: 1.1, alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(speedMenuButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 100 }); } }); tween(speedMenuButtonHighlight, { scaleX: 1.1, scaleY: 1.1, alpha: 0.6 }, { duration: 100, onFinish: function onFinish() { tween(speedMenuButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 100 }); } }); showSpeedControls(); return; } // Barrier zone between speed and language buttons (y: 1266-1296) if (y >= 1266 && y <= 1296) { return; // Block clicks in the barrier zone } } // Language menu section barrier if (languageMenuButton.visible && !speedOverlay.visible && !languageOverlay.visible) { // Check language menu button (DIL) with isolated click area if (x >= 824 && x <= 1224 && y >= 1296 && y <= 1396) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(languageMenuButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(languageMenuButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); // Animate shadow and highlight for depth effect tween(languageMenuButtonShadow, { scaleX: 1.1, scaleY: 1.1, alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(languageMenuButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 100 }); } }); tween(languageMenuButtonHighlight, { scaleX: 1.1, scaleY: 1.1, alpha: 0.6 }, { duration: 100, onFinish: function onFinish() { tween(languageMenuButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 100 }); } }); showLanguageControls(); return; } } // Language control buttons with barriers - only when language overlay is visible if (languageOverlay.visible) { // Turkish language button with isolated click area if (turkishButton.visible && x >= 654 && x <= 954 && y >= 1246 && y <= 1326) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(turkishButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(turkishButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); setLanguage('tr'); return; } // Barrier zone between Turkish and English buttons (x: 954-1094) if (x >= 954 && x <= 1094 && y >= 1246 && y <= 1326) { return; // Block clicks in barrier zone } // English language button with isolated click area if (englishButton.visible && x >= 1094 && x <= 1394 && y >= 1246 && y <= 1326) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(englishButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(englishButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); setLanguage('en'); return; } } // Speed control buttons with barriers - only when speed overlay is visible if (speedOverlay.visible) { // Normal speed button with isolated click area if (normalSpeedButton.visible && x >= 644 && x <= 844 && y >= 1246 && y <= 1326) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(normalSpeedButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(normalSpeedButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); setGameSpeed(1); return; } // Barrier zone between normal and 1.5x buttons (x: 844-924) if (x >= 844 && x <= 924 && y >= 1246 && y <= 1326) { return; // Block clicks in barrier zone } // 1.5X speed button with isolated click area if (speed15xButton.visible && x >= 924 && x <= 1124 && y >= 1246 && y <= 1326) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(speed15xButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(speed15xButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); setGameSpeed(1.5); return; } // Barrier zone between 1.5x and 2x buttons (x: 1124-1164) if (x >= 1124 && x <= 1164 && y >= 1246 && y <= 1326) { return; // Block clicks in barrier zone } // 2X speed button with isolated click area if (speed2xButton.visible && x >= 1164 && x <= 1344 && y >= 1246 && y <= 1326) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(speed2xButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(speed2xButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); setGameSpeed(2); return; } // Barrier zone between 2x and 2.5x buttons (x: 1344-1384) if (x >= 1344 && x <= 1384 && y >= 1246 && y <= 1326) { return; // Block clicks in barrier zone } // 2.5X speed button with isolated click area if (speed25xButton.visible && x >= 1384 && x <= 1564 && y >= 1246 && y <= 1326) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(speed25xButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(speed25xButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); setGameSpeed(2.5); return; } } // Check speed back button at x = 1024, y = 1516, size 300x100 if (speedBackButton.visible && x >= 874 && x <= 1174 && y >= 1466 && y <= 1566) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(speedBackButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(speedBackButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); hideSpeedControls(); return; } // Check language back button at x = 1024, y = 1516, size 300x100 if (languageBackButton.visible && x >= 874 && x <= 1174 && y >= 1466 && y <= 1566) { var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) return; lastButtonClickTime = currentTime; tween(languageBackButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(languageBackButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); hideLanguageControls(); return; } // Check close settings button (KAPAT) - centered at 1024x1516, button is 300x100 if (x >= 874 && x <= 1174 && y >= 1466 && y <= 1566) { // Prevent rapid clicks var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) { return; // Ignore click if too recent } lastButtonClickTime = currentTime; // Add visual feedback with tween tween(closeSettingsButton, { scaleX: 1.1, scaleY: 1.1 }, { duration: 100, onFinish: function onFinish() { tween(closeSettingsButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); } }); // Animate shadow and highlight for depth effect tween(closeSettingsButtonShadow, { scaleX: 1.1, scaleY: 1.1, alpha: 0.5 }, { duration: 100, onFinish: function onFinish() { tween(closeSettingsButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 100 }); } }); tween(closeSettingsButtonHighlight, { scaleX: 1.1, scaleY: 1.1, alpha: 0.6 }, { duration: 100, onFinish: function onFinish() { tween(closeSettingsButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 100 }); } }); hideSettingsMenu(); return; } return; // Don't process other clicks when settings menu is open } // Check cup click - cup is positioned at bottomRight with offset var cupX = 2048 - 100; // bottomRight.x + cupShape.x offset var cupY = 2732 - 230; // bottomRight.y + cupShape.y offset var cupSize = 120; // Cup asset size if (x >= cupX - cupSize / 2 && x <= cupX + cupSize / 2 && y >= cupY && y <= cupY + cupSize) { // Prevent rapid clicks var currentTime; try { currentTime = Date.now ? Date.now() : new Date().getTime(); } catch (e) { currentTime = 0; } if (currentTime - lastButtonClickTime < 500) { return; // Ignore click if too recent } lastButtonClickTime = currentTime; // Clear any existing high score displays first var existingDisplays = LK.gui.center.children; for (var k = existingDisplays.length - 1; k >= 0; k--) { var child = existingDisplays[k]; if (child && child.getText && child.getText().indexOf('EN YÜKSEK:') !== -1) { try { child.destroy(); } catch (e) { console.log("Error destroying high score display:", e); } } } // Clear any existing backgrounds for (var k = existingDisplays.length - 1; k >= 0; k--) { var child = existingDisplays[k]; if (child && child.tint === 0x000000 && child.width === 700) { try { child.destroy(); } catch (e) { console.log("Error destroying background:", e); } } } // Show highest score in a temporary display using storage var highScore = _storage && _storage.highScore || 0; var highScoreDisplay = new Text2(getText('highestScore') + ': ' + highScore, { size: 90, fill: 0xFFFF00 }); highScoreDisplay.anchor.set(0.5, 0.5); highScoreDisplay.stroke = 0x000000; highScoreDisplay.strokeThickness = 4; LK.gui.center.addChild(highScoreDisplay); highScoreDisplay.y = -100; // Add background for better visibility var highScoreBg = LK.getAsset('barrier', { anchorX: 0.5, anchorY: 0.5, width: 700, height: 160, alpha: 0.98 }); highScoreBg.tint = 0x000000; LK.gui.center.addChild(highScoreBg); highScoreBg.y = -100; // Move background behind text LK.gui.center.removeChild(highScoreBg); LK.gui.center.addChildAt(highScoreBg, LK.gui.center.getChildIndex(highScoreDisplay)); // Auto-hide after 3 seconds LK.setTimeout(function () { try { if (highScoreDisplay && highScoreDisplay.parent) { highScoreDisplay.destroy(); } if (highScoreBg && highScoreBg.parent) { highScoreBg.destroy(); } } catch (e) { console.log("Error in timeout cleanup:", e); } }, 3000); return; } if (gameOver || showGameOver) { // Check retry button (TEKRAR DENE) - centered at 1024x1466, button is 380x110 if (x >= 834 && x <= 1214 && y >= 1411 && y <= 1521) { // Prevent rapid clicks var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) { return; // Ignore click if too recent } lastButtonClickTime = currentTime; // Add enhanced visual feedback with tween tween(retryButton, { scaleX: 1.15, scaleY: 1.15 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(retryButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeInOut }); } }); // Animate shadow and highlight for depth effect tween(retryButtonShadow, { scaleX: 1.15, scaleY: 1.15, alpha: 0.5 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(retryButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 150, easing: tween.easeInOut }); } }); tween(retryButtonHighlight, { scaleX: 1.15, scaleY: 1.15, alpha: 0.6 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(retryButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 150, easing: tween.easeInOut }); } }); hideGameOverScreen(); resetGame(); // Show instruction screen instead of starting game directly startGameFromMenu(); return; } // Check menu button (ANA MENÜ) - centered at 1024x1616, button is 380x110 if (x >= 834 && x <= 1214 && y >= 1561 && y <= 1671) { // Prevent rapid clicks var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) { return; // Ignore click if too recent } lastButtonClickTime = currentTime; // Add enhanced visual feedback with tween tween(menuButton, { scaleX: 1.15, scaleY: 1.15 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(menuButton, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeInOut }); } }); // Animate shadow and highlight for depth effect tween(menuButtonShadow, { scaleX: 1.15, scaleY: 1.15, alpha: 0.5 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(menuButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.3 }, { duration: 150, easing: tween.easeInOut }); } }); tween(menuButtonHighlight, { scaleX: 1.15, scaleY: 1.15, alpha: 0.6 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(menuButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 150, easing: tween.easeInOut }); } }); hideGameOverScreen(); resetGame(); return; } return; } if (showMainMenu) { // Check play button click - centered at 1024x1266 (center.y = 1366 + playButton.y = -100), button is 400x120 if (playButton && playButton.visible && x >= 824 && x <= 1224 && y >= 1206 && y <= 1326) { // Prevent rapid clicks var currentTime = Date.now(); if (currentTime - lastButtonClickTime < 300) { return; // Ignore click if too recent } lastButtonClickTime = currentTime; // Enhanced click animation tween(playButton, { scaleX: 1.2, scaleY: 1.2, tint: 0xFFB74D }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(playButton, { scaleX: 1.0, scaleY: 1.0, tint: 0xFF9800 }, { duration: 150, easing: tween.easeInOut }); } }); // Animate shadow tween(playButtonShadow, { scaleX: 1.2, scaleY: 1.2, alpha: 0.6 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(playButtonShadow, { scaleX: 1.0, scaleY: 1.0, alpha: 0.4 }, { duration: 150, easing: tween.easeInOut }); } }); // Animate highlight tween(playButtonHighlight, { scaleX: 1.2, scaleY: 1.2, alpha: 0.8 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(playButtonHighlight, { scaleX: 1.0, scaleY: 1.0, alpha: 0.5 }, { duration: 150, easing: tween.easeInOut }); } }); // Animate text tween(playButtonText, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(playButtonText, { scaleX: 1.0, scaleY: 1.0 }, { duration: 150, easing: tween.easeInOut }); } }); startGameFromMenu(); return; } return; } if (!gameStarted) { gameStarted = true; instructionTxt.visible = false; // Remove invisible barriers when game starts if (topBarrier) { topBarrier.destroy(); topBarrier = null; } if (bottomBarrier) { bottomBarrier.destroy(); bottomBarrier = null; } } bird.flap(); }; // Main game loop game.update = function () { if (gameOver || showMainMenu || showGameOver) return; // Only run game logic if game has started if (gameStarted) { // Check ground and ceiling collision with proper bird size (bird is 80px tall, 120px wide) var birdRadius = 40; // Half of bird height for collision detection if (bird.y + birdRadius >= 2732 - 150 || bird.y - birdRadius <= 0) { gameOver = true; var currentScore = LK.getScore(); _storage.lastScore = currentScore; if (currentScore > (_storage.highScore || 0)) { _storage.highScore = currentScore; // High score is automatically saved to persistent storage via _storage reference } // Add to leaderboard if score > 0 if (currentScore > 0 && _storage) { var currentUsername = _storage.username || 'Oyuncu'; var playerExists = false; var leaderboardNames = _storage.globalLeaderboardNames || []; for (var i = 0; i < leaderboardNames.length; i++) { if (_storage.globalLeaderboardNames[i] === currentUsername) { if (currentScore > _storage.globalLeaderboardScores[i]) { _storage.globalLeaderboardScores[i] = currentScore; } playerExists = true; break; } } if (!playerExists) { _storage.globalLeaderboardNames.push(currentUsername); _storage.globalLeaderboardScores.push(currentScore); } } showGameOverScreen(currentScore); return; } // Check pipe collisions and scoring for (var i = 0; i < pipes.length; i++) { var pipe = pipes[i]; if (!pipe || !bird || pipe.destroyed || !pipe.parent) continue; // Check scoring first - only for pipes that haven't been passed yet if (!pipe.passed && pipe.x + 50 < bird.x) { pipe.passed = true; LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore().toString()); try { var scoreSound = LK.getSound('score'); if (scoreSound && scoreSound.play) { scoreSound.play(); } } catch (e) { console.log("Sound error:", e); } } // Only check collision for pipes that are close to the bird if (Math.abs(pipe.x - bird.x) < 150) { // Check if bird is within pipe horizontally using actual pipe width var pipeHalfWidth = (pipe.pipeWidth || 120) / 2; if (bird.x + 40 > pipe.x - pipeHalfWidth && bird.x - 40 < pipe.x + pipeHalfWidth) { // Check collision with top or bottom pipe - bird is 80px tall, so use 40px radius var birdTop = bird.y - 40; var birdBottom = bird.y + 40; var gapTop = pipe.gapCenterY - pipe.gapSize / 2; var gapBottom = pipe.gapCenterY + pipe.gapSize / 2; // Collision occurs if bird overlaps with pipe (outside the gap) if (birdTop < gapTop || birdBottom > gapBottom) { gameOver = true; var currentScore = LK.getScore(); _storage.lastScore = currentScore; if (currentScore > (_storage.highScore || 0)) { _storage.highScore = currentScore; // High score is automatically saved to persistent storage via _storage reference } // Add to leaderboard if score > 0 if (currentScore > 0) { var currentUsername = _storage.username; var playerExists = false; for (var j = 0; j < _storage.globalLeaderboardNames.length; j++) { if (_storage.globalLeaderboardNames[j] === currentUsername) { if (currentScore > _storage.globalLeaderboardScores[j]) { _storage.globalLeaderboardScores[j] = currentScore; } playerExists = true; break; } } if (!playerExists) { _storage.globalLeaderboardNames.push(currentUsername); _storage.globalLeaderboardScores.push(currentScore); } } showGameOverScreen(currentScore); return; } } } } // Create new pipes - maintain consistent spacing if (pipes.length === 0 || pipes.length > 0 && pipes[pipes.length - 1].x <= 2048 + 100 - pipeSpacing) { createPipe(); } // Remove off-screen pipes periodically using frame counter if (!game.frameCounter) game.frameCounter = 0; game.frameCounter++; if (game.frameCounter % 30 === 0) { for (var j = pipes.length - 1; j >= 0; j--) { if (pipes[j].x < -150) { pipes[j].destroy(); pipes.splice(j, 1); } } } } };
/****
* Classes
****/
var Bird = Container.expand(function () {
var self = Container.call(this);
var birdGraphics = self.attachAsset('bird', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocity = 0;
// Don't set gravity and jumpStrength here as gameSpeed may not be initialized yet
// They will be set dynamically in update method
self.flap = function () {
// Set velocity with more balanced scaling for consistent control
self.velocity = baseJumpStrength * Math.pow(gameSpeed, 0.8) * 1.05; // More balanced power scaling
// Create natural wing flap animation with squash and stretch
tween(birdGraphics, {
scaleX: 1.3,
scaleY: 0.8,
rotation: -0.4
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
// Secondary animation for natural wing movement
tween(birdGraphics, {
scaleX: 0.9,
scaleY: 1.1,
rotation: -0.2
}, {
duration: 120,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Return to normal with slight overshoot for natural feel
tween(birdGraphics, {
scaleX: 1.05,
scaleY: 0.95,
rotation: 0.1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(birdGraphics, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
}
});
}
});
// Create natural arc movement - bird moves slightly forward and up during flap
var currentX = self.x;
var currentY = self.y;
// First part of arc - upward and slightly forward
tween(self, {
x: currentX + 15,
y: currentY - 25
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Second part of arc - continue forward motion with natural deceleration
tween(self, {
x: currentX + 8
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
// Add slight horizontal bob for more natural movement
tween(birdGraphics, {
x: 3
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(birdGraphics, {
x: -2
}, {
duration: 180,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(birdGraphics, {
x: 0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
try {
var flapSound = LK.getSound('flap');
if (flapSound && flapSound.play) {
flapSound.play();
}
} catch (e) {
console.log("Flap sound error:", e);
}
};
self.update = function () {
if (!gameStarted) {
// Don't apply physics before game starts - keep bird completely still
self.velocity = 0;
self.y = 1366; // Keep bird at starting position
birdGraphics.rotation = 0; // Keep bird level
return;
}
// Update dynamic values based on current game speed with more balanced scaling
var gravity = baseGravity * Math.pow(gameSpeed, 0.7); // More balanced gravity scaling
var jumpStrength = baseJumpStrength * Math.pow(gameSpeed, 0.75); // More balanced jump scaling
self.velocity += gravity;
self.y += self.velocity;
// More responsive rotation based on velocity with better scaling
var rotationScale = 0.065 + (gameSpeed - 1) * 0.015; // Slightly more responsive at higher speeds
var targetRotation = Math.max(-0.5, Math.min(1.1, self.velocity * rotationScale));
// Smooth rotation transition using tween for more natural movement
if (Math.abs(birdGraphics.rotation - targetRotation) > 0.04) {
tween(birdGraphics, {
rotation: targetRotation
}, {
duration: 120,
easing: tween.easeOut
});
}
// Limit bird movement to screen bounds with proper collision detection
var birdRadius = 40; // Half of bird height for collision detection
if (self.y - birdRadius < 0) {
self.y = birdRadius;
self.velocity = 0;
}
if (self.y + birdRadius > 2732 - 150) {
self.y = 2732 - 150 - birdRadius;
self.velocity = 0;
}
};
return self;
});
var Pipe = Container.expand(function (gapCenterY) {
var self = Container.call(this);
self.gapSize = 750 + (gameSpeed - 1) * 50; // Dynamic gap size based on speed for better balance
self.speed = basePipeSpeed * gameSpeed;
self.passed = false;
self.gapCenterY = gapCenterY;
// Store pipe width for consistent collision detection
self.pipeWidth = 120;
// Calculate pipe heights
var topPipeHeight = Math.max(200, gapCenterY - self.gapSize / 2);
var bottomPipeHeight = Math.max(200, 2732 - 150 - (gapCenterY + self.gapSize / 2));
// =============== TOP PIPE CONSTRUCTION ===============
// Create main top pipe body with darker base color
var topPipe = self.attachAsset('topPipe', {
anchorX: 0.5,
anchorY: 1
});
topPipe.y = gapCenterY - self.gapSize / 2;
topPipe.height = topPipeHeight;
topPipe.width = self.pipeWidth;
topPipe.tint = 0x1B5E20; // Dark forest green base
// Create pipe shadow for depth
var topPipeShadow = self.attachAsset('topPipe', {
anchorX: 0.5,
anchorY: 1
});
topPipeShadow.y = gapCenterY - self.gapSize / 2;
topPipeShadow.height = topPipeHeight;
topPipeShadow.width = self.pipeWidth + 6;
topPipeShadow.x = 3;
topPipeShadow.tint = 0x0D2818; // Very dark shadow
topPipeShadow.alpha = 0.4;
// Create multiple highlight layers for realistic metallic sheen
var topPipeHighlight1 = self.attachAsset('pipeHighlight', {
anchorX: 0.5,
anchorY: 1
});
topPipeHighlight1.y = gapCenterY - self.gapSize / 2;
topPipeHighlight1.height = topPipeHeight;
topPipeHighlight1.width = 25;
topPipeHighlight1.x = -35;
topPipeHighlight1.tint = 0x66BB6A; // Bright green highlight
topPipeHighlight1.alpha = 0.8;
var topPipeHighlight2 = self.attachAsset('pipeHighlight', {
anchorX: 0.5,
anchorY: 1
});
topPipeHighlight2.y = gapCenterY - self.gapSize / 2;
topPipeHighlight2.height = topPipeHeight;
topPipeHighlight2.width = 12;
topPipeHighlight2.x = -42;
topPipeHighlight2.tint = 0xA5D6A7; // Lighter green shine
topPipeHighlight2.alpha = 0.9;
// Create realistic pipe joint rings every 150px
var numJoints = Math.floor(topPipeHeight / 150);
for (var j = 0; j < numJoints; j++) {
var jointY = gapCenterY - self.gapSize / 2 - (j + 1) * 150;
if (jointY > 50 && jointY < gapCenterY - self.gapSize / 2 - 50) {
// Don't create joints too close to top or gap area
// Main joint ring
var topJoint = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 0.5
});
topJoint.y = jointY;
topJoint.width = self.pipeWidth + 15;
topJoint.height = 20;
topJoint.tint = 0x37474F; // Blue-gray metallic
// Joint highlight
var topJointHighlight = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 0.5
});
topJointHighlight.y = jointY - 3;
topJointHighlight.width = self.pipeWidth + 12;
topJointHighlight.height = 8;
topJointHighlight.tint = 0x78909C; // Lighter metallic
topJointHighlight.alpha = 0.7;
}
}
// Rivets removed to prevent visual elements in gap area
// Enhanced top pipe cap with multiple layers
var topPipeCapBase = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 1
});
topPipeCapBase.y = gapCenterY - self.gapSize / 2;
topPipeCapBase.width = self.pipeWidth + 45;
topPipeCapBase.height = 35;
topPipeCapBase.tint = 0x263238; // Very dark base
var topPipeCap = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 1
});
topPipeCap.y = gapCenterY - self.gapSize / 2;
topPipeCap.width = self.pipeWidth + 35;
topPipeCap.height = 30;
topPipeCap.tint = 0x37474F; // Dark metallic
var topCapHighlight = self.attachAsset('pipeTop', {
anchorX: 0.5,
anchorY: 1
});
topCapHighlight.y = gapCenterY - self.gapSize / 2;
topCapHighlight.width = self.pipeWidth + 30;
topCapHighlight.height = 12;
topCapHighlight.tint = 0x78909C; // Metallic highlight
topCapHighlight.alpha = 0.8;
// =============== BOTTOM PIPE CONSTRUCTION ===============
// Create main bottom pipe body with darker base color
var bottomPipe = self.attachAsset('bottomPipe', {
anchorX: 0.5,
anchorY: 0
});
bottomPipe.y = gapCenterY + self.gapSize / 2;
bottomPipe.height = bottomPipeHeight;
bottomPipe.width = self.pipeWidth;
bottomPipe.tint = 0x1B5E20; // Dark forest green base
// Create pipe shadow for depth
var bottomPipeShadow = self.attachAsset('bottomPipe', {
anchorX: 0.5,
anchorY: 0
});
bottomPipeShadow.y = gapCenterY + self.gapSize / 2;
bottomPipeShadow.height = bottomPipeHeight;
bottomPipeShadow.width = self.pipeWidth + 6;
bottomPipeShadow.x = 3;
bottomPipeShadow.tint = 0x0D2818; // Very dark shadow
bottomPipeShadow.alpha = 0.4;
// Create multiple highlight layers for realistic metallic sheen
var bottomPipeHighlight1 = self.attachAsset('pipeHighlight', {
anchorX: 0.5,
anchorY: 0
});
bottomPipeHighlight1.y = gapCenterY + self.gapSize / 2;
bottomPipeHighlight1.height = bottomPipeHeight;
bottomPipeHighlight1.width = 25;
bottomPipeHighlight1.x = -35;
bottomPipeHighlight1.tint = 0x66BB6A; // Bright green highlight
bottomPipeHighlight1.alpha = 0.8;
var bottomPipeHighlight2 = self.attachAsset('pipeHighlight', {
anchorX: 0.5,
anchorY: 0
});
bottomPipeHighlight2.y = gapCenterY + self.gapSize / 2;
bottomPipeHighlight2.height = bottomPipeHeight;
bottomPipeHighlight2.width = 12;
bottomPipeHighlight2.x = -42;
bottomPipeHighlight2.tint = 0xA5D6A7; // Lighter green shine
bottomPipeHighlight2.alpha = 0.9;
// Create realistic pipe joint rings every 150px
var numBottomJoints = Math.floor(bottomPipeHeight / 150);
for (var j = 0; j < numBottomJoints; j++) {
var jointY = gapCenterY + self.gapSize / 2 + (j + 1) * 150;
if (jointY < 2732 - 200) {
// Don't create joints too close to ground
// Main joint ring
var bottomJoint = self.attachAsset('pipeBottom', {
anchorX: 0.5,
anchorY: 0.5
});
bottomJoint.y = jointY;
bottomJoint.width = self.pipeWidth + 15;
bottomJoint.height = 20;
bottomJoint.tint = 0x37474F; // Blue-gray metallic
// Joint highlight
var bottomJointHighlight = self.attachAsset('pipeBottom', {
anchorX: 0.5,
anchorY: 0.5
});
bottomJointHighlight.y = jointY + 3;
bottomJointHighlight.width = self.pipeWidth + 12;
bottomJointHighlight.height = 8;
bottomJointHighlight.tint = 0x78909C; // Lighter metallic
bottomJointHighlight.alpha = 0.7;
}
}
// Rivets removed to prevent visual elements in gap area
// Enhanced bottom pipe cap with multiple layers
var bottomPipeCapBase = self.attachAsset('pipeBottom', {
anchorX: 0.5,
anchorY: 0
});
bottomPipeCapBase.y = gapCenterY + self.gapSize / 2;
bottomPipeCapBase.width = self.pipeWidth + 45;
bottomPipeCapBase.height = 35;
bottomPipeCapBase.tint = 0x263238; // Very dark base
var bottomPipeCap = self.attachAsset('pipeBottom', {
anchorX: 0.5,
anchorY: 0
});
bottomPipeCap.y = gapCenterY + self.gapSize / 2;
bottomPipeCap.width = self.pipeWidth + 35;
bottomPipeCap.height = 30;
bottomPipeCap.tint = 0x37474F; // Dark metallic
var bottomCapHighlight = self.attachAsset('pipeBottom', {
anchorX: 0.5,
anchorY: 0
});
bottomCapHighlight.y = gapCenterY + self.gapSize / 2;
bottomCapHighlight.width = self.pipeWidth + 30;
bottomCapHighlight.height = 12;
bottomCapHighlight.tint = 0x78909C; // Metallic highlight
bottomCapHighlight.alpha = 0.8;
self.update = function () {
if (!gameStarted) {
// Don't move pipes before game starts
return;
}
// Update dynamic speed based on current game speed
self.speed = basePipeSpeed * gameSpeed;
self.x += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game();
/****
* Game Code
****/
// Initialize plugins with proper error handling
// Game variables
var tween;
var storage;
try {
tween = LK.import("@upit/tween.v1");
storage = LK.import("@upit/storage.v1", {
highScore: 0,
language: 'en',
username: 'Player1',
globalLeaderboardNames: [],
globalLeaderboardScores: [],
lastScore: 0
});
} catch (e) {
console.log("Plugin import error:", e);
// Provide comprehensive fallback objects to prevent undefined errors
tween = function tween(target, props, options) {
return {
duration: options ? options.duration || 0 : 0,
onFinish: options && options.onFinish ? options.onFinish : function () {}
};
};
storage = {
highScore: 0,
language: 'en',
username: 'Player1',
globalLeaderboardNames: [],
globalLeaderboardScores: [],
lastScore: 0
};
}
var bird;
var pipes = [];
var ground;
var topBarrier;
var bottomBarrier;
var gameStarted = false;
var gameOver = false;
var showMainMenu = true;
var showGameOver = false;
var pipeSpacing = 500 + gameSpeed * 50; // Dynamic spacing based on speed for better balance
var buttonClickTimeout = null; // Prevent rapid button clicks
var lastButtonClickTime = 0; // Track last button click time
var gameSpeed = 1; // Current game speed multiplier (1 = normal, 2 = 2x, 3 = 3x)
var baseGravity = 0.55; // Base gravity for bird - fine-tuned for better control
var baseJumpStrength = -9.5; // Base jump strength for bird - fine-tuned for better balance
var basePipeSpeed = -3; // Base pipe movement speed
// Initialize game speed properly
gameSpeed = 1;
// Initialize storage with defaults
var _storage = storage;
// Create score text display
var scoreTxt = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.stroke = 0x000000;
scoreTxt.strokeThickness = 5;
try {
if (LK.gui && LK.gui.top) {
LK.gui.top.addChild(scoreTxt);
}
} catch (e) {
console.log("GUI score text error:", e);
}
// Create cup shape for score
var cupShape;
try {
cupShape = LK.getAsset('cup', {
anchorX: 0.5,
anchorY: 0
});
cupShape.tint = 0xFFD700;
if (LK.gui && LK.gui.bottomRight) {
LK.gui.bottomRight.addChild(cupShape);
cupShape.y = -230;
cupShape.x = -100;
}
} catch (e) {
console.log("Cup shape error:", e);
}
// Create main menu elements
var mainMenuTitle = new Text2('FLAPPY BIRD', {
size: 90,
fill: 0xFFD700
});
mainMenuTitle.anchor.set(0.5, 0.5);
mainMenuTitle.stroke = 0x000000;
mainMenuTitle.strokeThickness = 5;
try {
if (LK.gui && LK.gui.center) {
LK.gui.center.addChild(mainMenuTitle);
mainMenuTitle.y = -280;
}
} catch (e) {
console.log("Main menu title error:", e);
}
// Create instruction text
var instructionTxt = new Text2('TIKLA VE OYNA!', {
size: 50,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 0.5);
instructionTxt.stroke = 0x000000;
instructionTxt.strokeThickness = 3;
instructionTxt.visible = false;
instructionTxt.y = -50;
// Remove background shape for instruction text - no longer needed
LK.gui.center.addChild(instructionTxt);
// Create game over screen elements
var gameOverBg = LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
width: 1600,
height: 1200,
alpha: 0.95
});
gameOverBg.tint = 0x2F4F4F;
gameOverBg.visible = false;
LK.gui.center.addChild(gameOverBg);
var gameOverTitle = new Text2('OYUN BİTTİ', {
size: 120,
fill: 0xFFFFFF
});
gameOverTitle.anchor.set(0.5, 0.5);
gameOverTitle.stroke = 0x000000;
gameOverTitle.strokeThickness = 6;
gameOverTitle.visible = false;
LK.gui.center.addChild(gameOverTitle);
gameOverTitle.y = -300;
var finalScoreText = new Text2('SKOR: 0', {
size: 80,
fill: 0xFFFFFF
});
finalScoreText.anchor.set(0.5, 0.5);
finalScoreText.stroke = 0x000000;
finalScoreText.strokeThickness = 4;
finalScoreText.visible = false;
LK.gui.center.addChild(finalScoreText);
finalScoreText.y = -150;
var bestScoreText = new Text2('EN İYİ: 0', {
size: 60,
fill: 0xFFD700
});
bestScoreText.anchor.set(0.5, 0.5);
bestScoreText.stroke = 0x000000;
bestScoreText.strokeThickness = 3;
bestScoreText.visible = false;
LK.gui.center.addChild(bestScoreText);
bestScoreText.y = -50;
// Create retry button with enhanced styling
var retryButton = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 380,
height: 110,
alpha: 1.0
});
retryButton.tint = 0xFF9800; // Orange like original Flappy Bird
retryButton.visible = false;
LK.gui.center.addChild(retryButton);
retryButton.y = 100;
// Add retry button shadow for depth
var retryButtonShadow = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 380,
height: 110,
alpha: 0.3
});
retryButtonShadow.tint = 0xE65100; // Darker orange shadow
retryButtonShadow.visible = false;
LK.gui.center.addChild(retryButtonShadow);
retryButtonShadow.y = 108; // Offset shadow slightly down
retryButtonShadow.x = 4; // Offset shadow slightly right
// Add retry button highlight
var retryButtonHighlight = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 350,
height: 85,
alpha: 0.4
});
retryButtonHighlight.tint = 0xFFB74D; // Lighter orange highlight
retryButtonHighlight.visible = false;
LK.gui.center.addChild(retryButtonHighlight);
retryButtonHighlight.y = 92; // Offset highlight slightly up
var retryButtonText = new Text2('TEKRAR DENE', {
size: 44,
fill: 0xFFFFFF
});
retryButtonText.anchor.set(0.5, 0.5);
retryButtonText.stroke = 0xE65100;
retryButtonText.strokeThickness = 3;
retryButtonText.visible = false;
LK.gui.center.addChild(retryButtonText);
retryButtonText.y = 100;
// Create menu button with enhanced styling
var menuButton = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 380,
height: 110,
alpha: 1.0
});
menuButton.tint = 0xF44336; // Red like original Flappy Bird
menuButton.visible = false;
LK.gui.center.addChild(menuButton);
menuButton.y = 250;
// Add menu button shadow for depth
var menuButtonShadow = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 380,
height: 110,
alpha: 0.3
});
menuButtonShadow.tint = 0xD32F2F; // Darker red shadow
menuButtonShadow.visible = false;
LK.gui.center.addChild(menuButtonShadow);
menuButtonShadow.y = 258; // Offset shadow slightly down
menuButtonShadow.x = 4; // Offset shadow slightly right
// Add menu button highlight
var menuButtonHighlight = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 350,
height: 85,
alpha: 0.4
});
menuButtonHighlight.tint = 0xEF5350; // Lighter red highlight
menuButtonHighlight.visible = false;
LK.gui.center.addChild(menuButtonHighlight);
menuButtonHighlight.y = 242; // Offset highlight slightly up
var menuButtonText = new Text2('ANA MENÜ', {
size: 44,
fill: 0xFFFFFF
});
menuButtonText.anchor.set(0.5, 0.5);
menuButtonText.stroke = 0xD32F2F;
menuButtonText.strokeThickness = 3;
menuButtonText.visible = false;
LK.gui.center.addChild(menuButtonText);
menuButtonText.y = 250;
// Create separate settings button element
var settingsButton = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 100,
alpha: 1.0
});
settingsButton.tint = 0x8E44AD;
try {
if (LK.gui && LK.gui.topRight) {
LK.gui.topRight.addChild(settingsButton);
settingsButton.x = -80;
settingsButton.y = 80;
}
} catch (e) {
console.log("Settings button error:", e);
}
// Create separate settings button shadow element
var settingsButtonShadow = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 100,
alpha: 0.3
});
settingsButtonShadow.tint = 0x6B2C91; // Darker purple shadow
try {
if (LK.gui && LK.gui.topRight) {
LK.gui.topRight.addChild(settingsButtonShadow);
settingsButtonShadow.x = -77;
settingsButtonShadow.y = 83;
}
} catch (e) {
console.log("Settings button shadow error:", e);
}
// Create separate settings button highlight element
var settingsButtonHighlight = LK.getAsset('playButtonOval', {
anchorX: 0.5,
anchorY: 0.5,
width: 85,
height: 85,
alpha: 0.4
});
settingsButtonHighlight.tint = 0xBB8FCE; // Lighter purple highlight
try {
if (LK.gui && LK.gui.topRight) {
LK.gui.topRight.addChild(settingsButtonHighlight);
settingsButtonHighlight.x = -80;
settingsButtonHighlight.y = 77;
}
} catch (e) {
console.log("Settings button highlight error:", e);
}
// Create separate settings icon text element
var settingsIcon = new Text2('⚙', {
size: 60,
fill: 0xFFFFFF
});
settingsIcon.anchor.set(0.5, 0.5);
settingsIcon.stroke = 0x6B2C91;
settingsIcon.strokeThickness = 2;
try {
if (LK.gui && LK.gui.topRight) {
LK.gui.topRight.addChild(settingsIcon);
settingsIcon.x = -80;
settingsIcon.y = 80;
}
} catch (e) {
console.log("Settings icon error:", e);
}
// Create settings menu overlay (initially hidden)
var settingsOverlay = LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 1.0
});
settingsOverlay.tint = 0x2F4F4F;
settingsOverlay.visible = false;
LK.gui.center.addChild(settingsOverlay);
var settingsTitle = new Text2('AYARLAR', {
size: 100,
fill: 0xFFFFFF
});
settingsTitle.anchor.set(0.5, 0.5);
settingsTitle.stroke = 0x000000;
settingsTitle.strokeThickness = 5;
settingsTitle.visible = false;
LK.gui.center.addChild(settingsTitle);
settingsTitle.y = -300;
// Create close settings button with modern rectangular design
var closeSettingsButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 70,
alpha: 1.0
});
closeSettingsButton.tint = 0x95A5A6;
closeSettingsButton.visible = false;
LK.gui.center.addChild(closeSettingsButton);
closeSettingsButton.y = 150;
// Add close button shadow for depth
var closeSettingsButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 70,
alpha: 0.3
});
closeSettingsButtonShadow.tint = 0x7F8C8D;
closeSettingsButtonShadow.visible = false;
LK.gui.center.addChild(closeSettingsButtonShadow);
closeSettingsButtonShadow.y = 155;
closeSettingsButtonShadow.x = 3;
// Add close button highlight
var closeSettingsButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 55,
alpha: 0.4
});
closeSettingsButtonHighlight.tint = 0xBDC3C7;
closeSettingsButtonHighlight.visible = false;
LK.gui.center.addChild(closeSettingsButtonHighlight);
closeSettingsButtonHighlight.y = 145;
var closeSettingsText = new Text2('KAPAT', {
size: 36,
fill: 0xFFFFFF
});
closeSettingsText.anchor.set(0.5, 0.5);
closeSettingsText.stroke = 0x7F8C8D;
closeSettingsText.strokeThickness = 2;
closeSettingsText.visible = false;
LK.gui.center.addChild(closeSettingsText);
closeSettingsText.y = 150;
// Create speed menu button with modern rectangular design
var speedMenuButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 340,
height: 75,
alpha: 1.0
});
speedMenuButton.tint = 0x3498DB;
speedMenuButton.visible = false;
LK.gui.center.addChild(speedMenuButton);
speedMenuButton.y = -150;
// Add speed button shadow for depth
var speedMenuButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 340,
height: 75,
alpha: 0.3
});
speedMenuButtonShadow.tint = 0x2980B9;
speedMenuButtonShadow.visible = false;
LK.gui.center.addChild(speedMenuButtonShadow);
speedMenuButtonShadow.y = -145;
speedMenuButtonShadow.x = 3;
// Add speed button highlight
var speedMenuButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 320,
height: 60,
alpha: 0.4
});
speedMenuButtonHighlight.tint = 0x5DADE2;
speedMenuButtonHighlight.visible = false;
LK.gui.center.addChild(speedMenuButtonHighlight);
speedMenuButtonHighlight.y = -155;
var speedMenuText = new Text2('HIZ', {
size: 42,
fill: 0xFFFFFF
});
speedMenuText.anchor.set(0.5, 0.5);
speedMenuText.stroke = 0x2980B9;
speedMenuText.strokeThickness = 2;
speedMenuText.visible = false;
LK.gui.center.addChild(speedMenuText);
speedMenuText.y = -150;
// Create language menu button with modern rectangular design
var languageMenuButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 340,
height: 75,
alpha: 1.0
});
languageMenuButton.tint = 0x9B59B6;
languageMenuButton.visible = false;
LK.gui.center.addChild(languageMenuButton);
languageMenuButton.y = -20;
// Add language button shadow for depth
var languageMenuButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 340,
height: 75,
alpha: 0.3
});
languageMenuButtonShadow.tint = 0x8E44AD;
languageMenuButtonShadow.visible = false;
LK.gui.center.addChild(languageMenuButtonShadow);
languageMenuButtonShadow.y = -15;
languageMenuButtonShadow.x = 3;
// Add language button highlight
var languageMenuButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 320,
height: 60,
alpha: 0.4
});
languageMenuButtonHighlight.tint = 0xBB8FCE;
languageMenuButtonHighlight.visible = false;
LK.gui.center.addChild(languageMenuButtonHighlight);
languageMenuButtonHighlight.y = -25;
var languageMenuText = new Text2('DİL', {
size: 42,
fill: 0xFFFFFF
});
languageMenuText.anchor.set(0.5, 0.5);
languageMenuText.stroke = 0x8E44AD;
languageMenuText.strokeThickness = 2;
languageMenuText.visible = false;
LK.gui.center.addChild(languageMenuText);
languageMenuText.y = -20;
// Create new speed control elements
var speedTitle = new Text2('HIZ AYARI', {
size: 80,
fill: 0xFFFFFF
});
speedTitle.anchor.set(0.5, 0.5);
speedTitle.stroke = 0x000000;
speedTitle.strokeThickness = 4;
speedTitle.visible = false;
LK.gui.center.addChild(speedTitle);
speedTitle.y = -200;
// Create speed option buttons with modern rectangular design
var normalSpeedButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 1.0
});
normalSpeedButton.tint = 0x27AE60;
normalSpeedButton.visible = false;
LK.gui.center.addChild(normalSpeedButton);
normalSpeedButton.y = -80;
normalSpeedButton.x = -280;
// Add normal speed button shadow
var normalSpeedButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 0.3
});
normalSpeedButtonShadow.tint = 0x1E8449;
normalSpeedButtonShadow.visible = false;
LK.gui.center.addChild(normalSpeedButtonShadow);
normalSpeedButtonShadow.y = -75;
normalSpeedButtonShadow.x = -277;
// Add normal speed button highlight
var normalSpeedButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 160,
height: 50,
alpha: 0.4
});
normalSpeedButtonHighlight.tint = 0x58D68D;
normalSpeedButtonHighlight.visible = false;
LK.gui.center.addChild(normalSpeedButtonHighlight);
normalSpeedButtonHighlight.y = -85;
normalSpeedButtonHighlight.x = -280;
var normalSpeedText = new Text2('NORMAL', {
size: 32,
fill: 0xFFFFFF
});
normalSpeedText.anchor.set(0.5, 0.5);
normalSpeedText.stroke = 0x1E8449;
normalSpeedText.strokeThickness = 2;
normalSpeedText.visible = false;
LK.gui.center.addChild(normalSpeedText);
normalSpeedText.y = -80;
normalSpeedText.x = -280;
var speed15xButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 1.0
});
speed15xButton.tint = 0xF39C12;
speed15xButton.visible = false;
LK.gui.center.addChild(speed15xButton);
speed15xButton.y = -80;
speed15xButton.x = 0;
// Add 1.5x speed button shadow
var speed15xButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 0.3
});
speed15xButtonShadow.tint = 0xD68910;
speed15xButtonShadow.visible = false;
LK.gui.center.addChild(speed15xButtonShadow);
speed15xButtonShadow.y = -75;
speed15xButtonShadow.x = 3;
// Add 1.5x speed button highlight
var speed15xButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 160,
height: 50,
alpha: 0.4
});
speed15xButtonHighlight.tint = 0xF7DC6F;
speed15xButtonHighlight.visible = false;
LK.gui.center.addChild(speed15xButtonHighlight);
speed15xButtonHighlight.y = -85;
speed15xButtonHighlight.x = 0;
var speed15xText = new Text2('1.5X', {
size: 32,
fill: 0xFFFFFF
});
speed15xText.anchor.set(0.5, 0.5);
speed15xText.stroke = 0xD68910;
speed15xText.strokeThickness = 2;
speed15xText.visible = false;
LK.gui.center.addChild(speed15xText);
speed15xText.y = -80;
speed15xText.x = 0;
var speed2xButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 1.0
});
speed2xButton.tint = 0xE74C3C;
speed2xButton.visible = false;
LK.gui.center.addChild(speed2xButton);
speed2xButton.y = -80;
speed2xButton.x = 180;
// Add 2x speed button shadow
var speed2xButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 0.3
});
speed2xButtonShadow.tint = 0xC0392B;
speed2xButtonShadow.visible = false;
LK.gui.center.addChild(speed2xButtonShadow);
speed2xButtonShadow.y = -75;
speed2xButtonShadow.x = 183;
// Add 2x speed button highlight
var speed2xButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 160,
height: 50,
alpha: 0.4
});
speed2xButtonHighlight.tint = 0xF1948A;
speed2xButtonHighlight.visible = false;
LK.gui.center.addChild(speed2xButtonHighlight);
speed2xButtonHighlight.y = -85;
speed2xButtonHighlight.x = 180;
var speed2xText = new Text2('2X', {
size: 32,
fill: 0xFFFFFF
});
speed2xText.anchor.set(0.5, 0.5);
speed2xText.stroke = 0xC0392B;
speed2xText.strokeThickness = 2;
speed2xText.visible = false;
LK.gui.center.addChild(speed2xText);
speed2xText.y = -80;
speed2xText.x = 180;
// Create 2.5x speed button
var speed25xButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 1.0
});
speed25xButton.tint = 0x9C27B0;
speed25xButton.visible = false;
LK.gui.center.addChild(speed25xButton);
speed25xButton.y = -80;
speed25xButton.x = 360;
// Add 2.5x speed button shadow
var speed25xButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 180,
height: 65,
alpha: 0.3
});
speed25xButtonShadow.tint = 0x7B1FA2;
speed25xButtonShadow.visible = false;
LK.gui.center.addChild(speed25xButtonShadow);
speed25xButtonShadow.y = -75;
speed25xButtonShadow.x = 363;
// Add 2.5x speed button highlight
var speed25xButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 160,
height: 50,
alpha: 0.4
});
speed25xButtonHighlight.tint = 0xBA68C8;
speed25xButtonHighlight.visible = false;
LK.gui.center.addChild(speed25xButtonHighlight);
speed25xButtonHighlight.y = -85;
speed25xButtonHighlight.x = 360;
var speed25xText = new Text2('2.5X', {
size: 32,
fill: 0xFFFFFF
});
speed25xText.anchor.set(0.5, 0.5);
speed25xText.stroke = 0x7B1FA2;
speed25xText.strokeThickness = 2;
speed25xText.visible = false;
LK.gui.center.addChild(speed25xText);
speed25xText.y = -80;
speed25xText.x = 360;
// Current speed indicator
var currentSpeedText = new Text2('MEVCUT: NORMAL', {
size: 50,
fill: 0xFFD700
});
currentSpeedText.anchor.set(0.5, 0.5);
currentSpeedText.stroke = 0x000000;
currentSpeedText.strokeThickness = 3;
currentSpeedText.visible = false;
LK.gui.center.addChild(currentSpeedText);
currentSpeedText.y = 30;
// Create back button for speed controls with modern rectangular design
var speedBackButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 65,
alpha: 1.0
});
speedBackButton.tint = 0x7F8C8D;
speedBackButton.visible = false;
LK.gui.center.addChild(speedBackButton);
speedBackButton.y = 150;
// Add speed back button shadow
var speedBackButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 65,
alpha: 0.3
});
speedBackButtonShadow.tint = 0x566573;
speedBackButtonShadow.visible = false;
LK.gui.center.addChild(speedBackButtonShadow);
speedBackButtonShadow.y = 155;
speedBackButtonShadow.x = 3;
// Add speed back button highlight
var speedBackButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 50,
alpha: 0.4
});
speedBackButtonHighlight.tint = 0xABB2B9;
speedBackButtonHighlight.visible = false;
LK.gui.center.addChild(speedBackButtonHighlight);
speedBackButtonHighlight.y = 145;
var speedBackText = new Text2('GERİ', {
size: 36,
fill: 0xFFFFFF
});
speedBackText.anchor.set(0.5, 0.5);
speedBackText.stroke = 0x566573;
speedBackText.strokeThickness = 2;
speedBackText.visible = false;
LK.gui.center.addChild(speedBackText);
speedBackText.y = 150;
// Create invisible barrier blocks to constrain bird before game starts
var topBarrier = game.addChild(LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 1
}));
topBarrier.x = 400;
topBarrier.y = 1316; // 50 pixels above bird
topBarrier.alpha = 0; // Make invisible
var bottomBarrier = game.addChild(LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0
}));
bottomBarrier.x = 400;
bottomBarrier.y = 1416; // 50 pixels below bird
bottomBarrier.alpha = 0; // Make invisible
// Create and add background image (appears behind barriers but in front of other elements)
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
background.x = 0;
background.y = 0;
// Scale background to fill screen for better performance
background.scaleX = 2;
background.scaleY = 2;
// Create ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 1
}));
ground.x = 0;
ground.y = 2732;
ground.tint = 0x654321;
// Create bird
bird = game.addChild(new Bird());
bird.x = 400;
bird.y = 1366;
// Initialize bird properly
bird.velocity = 0;
// Create pipe function
function createPipe() {
// Define safe boundaries for gap center to ensure both pipes have reasonable heights
var minGapY = 700; // Increased minimum gap center position for better clearance
var maxGapY = 1900; // Adjusted maximum gap center position for better clearance
var gapCenterY;
// Create more varied random patterns with better distribution
var randomPattern = Math.random();
if (randomPattern < 0.4) {
// 40% chance for high gaps (easier to navigate)
gapCenterY = minGapY + Math.random() * 300;
} else if (randomPattern < 0.7) {
// 30% chance for middle gaps (moderate difficulty)
gapCenterY = 1000 + Math.random() * 500;
} else {
// 30% chance for low gaps (more challenging but still passable)
gapCenterY = maxGapY - Math.random() * 300;
}
// Add some variation based on current score for progressive difficulty
var currentScore = LK.getScore();
if (currentScore > 10) {
// After score 10, make gaps slightly more challenging
var difficultyFactor = Math.min(0.8, currentScore / 50); // Max 80% difficulty increase
var centerPull = 1300; // Pull towards center-high area
gapCenterY = gapCenterY + (centerPull - gapCenterY) * difficultyFactor * 0.3;
}
// Ensure the gap stays within safe boundaries
gapCenterY = Math.max(minGapY, Math.min(maxGapY, gapCenterY));
var pipe = new Pipe(gapCenterY);
// Calculate position based on last pipe position + consistent spacing
if (pipes.length === 0) {
pipe.x = 2048 + 100; // First pipe position - brought closer
} else {
pipe.x = pipes[pipes.length - 1].x + pipeSpacing; // Consistent spacing from last pipe
}
;
pipes.push(pipe);
game.addChild(pipe);
}
// Reset game function
function resetGame() {
// Reset bird
bird.x = 400;
bird.y = 1366;
bird.velocity = 0;
// Clear pipes
for (var i = pipes.length - 1; i >= 0; i--) {
pipes[i].destroy();
}
pipes = [];
// Reset variables
gameStarted = false;
gameOver = false;
showMainMenu = true;
showGameOver = false;
// Hide game over screen
hideGameOverScreen();
LK.setScore(0);
scoreTxt.setText('0');
// Show main menu
mainMenuTitle.visible = true;
// Show play button elements
if (playButton) playButton.visible = true;
if (playButtonShadow) playButtonShadow.visible = true;
if (playButtonHighlight) playButtonHighlight.visible = true;
if (playButtonText) playButtonText.visible = true;
// Start play button animation
startPlayButtonAnimation();
// Show all settings button elements
settingsButton.visible = true;
settingsButtonShadow.visible = true;
settingsButtonHighlight.visible = true;
settingsIcon.visible = true;
// Show cup shape (high score indicator)
if (cupShape) cupShape.visible = true;
// Hide instruction
instructionTxt.visible = false;
// Clear existing barriers if they exist
if (topBarrier) {
topBarrier.destroy();
topBarrier = null;
}
if (bottomBarrier) {
bottomBarrier.destroy();
bottomBarrier = null;
}
// Recreate invisible barriers
topBarrier = game.addChild(LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 1
}));
topBarrier.x = 400;
topBarrier.y = 1316; // 50 pixels above bird
topBarrier.alpha = 0; // Make invisible
bottomBarrier = game.addChild(LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0
}));
bottomBarrier.x = 400;
bottomBarrier.y = 1416; // 50 pixels below bird
bottomBarrier.alpha = 0; // Make invisible
// Create initial pipes
createPipe();
createPipe();
}
// Function to start game from main menu
function startGameFromMenu() {
showMainMenu = false;
// Hide main menu elements
mainMenuTitle.visible = false;
// Hide play button elements
if (playButton) playButton.visible = false;
if (playButtonShadow) playButtonShadow.visible = false;
if (playButtonHighlight) playButtonHighlight.visible = false;
if (playButtonText) playButtonText.visible = false;
// Hide all settings button elements
settingsButton.visible = false;
settingsButtonShadow.visible = false;
settingsButtonHighlight.visible = false;
settingsIcon.visible = false;
// Hide cup shape (high score indicator)
if (cupShape) cupShape.visible = false;
// Show instruction
instructionTxt.visible = true;
}
// Function to show game over screen
function showGameOverScreen(finalScore) {
showGameOver = true;
gameStarted = false;
showMainMenu = false;
// Hide instruction
instructionTxt.visible = false;
// Show game over elements
gameOverBg.visible = true;
gameOverTitle.visible = true;
finalScoreText.visible = true;
bestScoreText.visible = true;
retryButton.visible = true;
retryButtonText.visible = true;
retryButtonShadow.visible = true;
retryButtonHighlight.visible = true;
menuButton.visible = true;
menuButtonText.visible = true;
menuButtonShadow.visible = true;
menuButtonHighlight.visible = true;
// Update score displays
finalScoreText.setText(getText('score') + ': ' + finalScore);
// Use proper text sizing
if (finalScoreText.width > 600) {
var newSize = Math.max(50, Math.floor(80 * 600 / finalScoreText.width));
finalScoreText.style = {
size: newSize,
fill: finalScoreText.style.fill
};
}
// Always show the current high score from storage
var currentHighScore = _storage && _storage.highScore ? _storage.highScore : 0;
bestScoreText.setText(getText('bestScore') + ': ' + currentHighScore);
// Use proper text sizing
if (bestScoreText.width > 600) {
var newSize = Math.max(40, Math.floor(60 * 600 / bestScoreText.width));
bestScoreText.style = {
size: newSize,
fill: bestScoreText.style.fill
};
}
// Add entrance animation for buttons
tween(retryButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(retryButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
tween(menuButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(menuButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
// Function to hide game over screen
function hideGameOverScreen() {
showGameOver = false;
// Hide game over elements
gameOverBg.visible = false;
gameOverTitle.visible = false;
finalScoreText.visible = false;
bestScoreText.visible = false;
retryButton.visible = false;
retryButtonText.visible = false;
retryButtonShadow.visible = false;
retryButtonHighlight.visible = false;
menuButton.visible = false;
menuButtonText.visible = false;
menuButtonShadow.visible = false;
menuButtonHighlight.visible = false;
}
// Create speed overlay background - moved to end to ensure it's on top
var speedOverlay = LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 1.0
});
speedOverlay.tint = 0x2F4F4F;
speedOverlay.visible = false;
// Add to front to ensure visibility above all other elements
LK.gui.center.addChild(speedOverlay);
// Create language overlay background
var languageOverlay = LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 1.0
});
languageOverlay.tint = 0x2F4F4F;
languageOverlay.visible = false;
LK.gui.center.addChild(languageOverlay);
// Create language control title
var languageTitle = new Text2('DİL SEÇENEKLERİ', {
size: 80,
fill: 0xFFFFFF
});
languageTitle.anchor.set(0.5, 0.5);
languageTitle.stroke = 0x000000;
languageTitle.strokeThickness = 4;
languageTitle.visible = false;
LK.gui.center.addChild(languageTitle);
languageTitle.y = -200;
// Create language option buttons with modern rectangular design
var turkishButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 65,
alpha: 1.0
});
turkishButton.tint = 0x27AE60;
turkishButton.visible = false;
LK.gui.center.addChild(turkishButton);
turkishButton.y = -80;
turkishButton.x = -220;
// Add Turkish button shadow
var turkishButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 65,
alpha: 0.3
});
turkishButtonShadow.tint = 0x1E8449;
turkishButtonShadow.visible = false;
LK.gui.center.addChild(turkishButtonShadow);
turkishButtonShadow.y = -75;
turkishButtonShadow.x = -217;
// Add Turkish button highlight
var turkishButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 50,
alpha: 0.4
});
turkishButtonHighlight.tint = 0x58D68D;
turkishButtonHighlight.visible = false;
LK.gui.center.addChild(turkishButtonHighlight);
turkishButtonHighlight.y = -85;
turkishButtonHighlight.x = -220;
var turkishText = new Text2('TÜRKÇE', {
size: 32,
fill: 0xFFFFFF
});
turkishText.anchor.set(0.5, 0.5);
turkishText.stroke = 0x1E8449;
turkishText.strokeThickness = 2;
turkishText.visible = false;
LK.gui.center.addChild(turkishText);
turkishText.y = -80;
turkishText.x = -220;
var englishButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 65,
alpha: 1.0
});
englishButton.tint = 0x3498DB;
englishButton.visible = false;
LK.gui.center.addChild(englishButton);
englishButton.y = -80;
englishButton.x = 220;
// Add English button shadow
var englishButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 260,
height: 65,
alpha: 0.3
});
englishButtonShadow.tint = 0x2980B9;
englishButtonShadow.visible = false;
LK.gui.center.addChild(englishButtonShadow);
englishButtonShadow.y = -75;
englishButtonShadow.x = 223;
// Add English button highlight
var englishButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 240,
height: 50,
alpha: 0.4
});
englishButtonHighlight.tint = 0x85C1E9;
englishButtonHighlight.visible = false;
LK.gui.center.addChild(englishButtonHighlight);
englishButtonHighlight.y = -85;
englishButtonHighlight.x = 220;
var englishText = new Text2('ENGLISH', {
size: 32,
fill: 0xFFFFFF
});
englishText.anchor.set(0.5, 0.5);
englishText.stroke = 0x2980B9;
englishText.strokeThickness = 2;
englishText.visible = false;
LK.gui.center.addChild(englishText);
englishText.y = -80;
englishText.x = 220;
// Current language indicator
var currentLanguageText = new Text2('MEVCUT: TÜRKÇE', {
size: 50,
fill: 0xFFD700
});
currentLanguageText.anchor.set(0.5, 0.5);
currentLanguageText.stroke = 0x000000;
currentLanguageText.strokeThickness = 3;
currentLanguageText.visible = false;
LK.gui.center.addChild(currentLanguageText);
currentLanguageText.y = 30;
// Create back button for language controls with modern rectangular design
var languageBackButton = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 65,
alpha: 1.0
});
languageBackButton.tint = 0x7F8C8D;
languageBackButton.visible = false;
LK.gui.center.addChild(languageBackButton);
languageBackButton.y = 150;
// Add language back button shadow
var languageBackButtonShadow = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 220,
height: 65,
alpha: 0.3
});
languageBackButtonShadow.tint = 0x566573;
languageBackButtonShadow.visible = false;
LK.gui.center.addChild(languageBackButtonShadow);
languageBackButtonShadow.y = 155;
languageBackButtonShadow.x = 3;
// Add language back button highlight
var languageBackButtonHighlight = LK.getAsset('settingsButtonRect', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 50,
alpha: 0.4
});
languageBackButtonHighlight.tint = 0xABB2B9;
languageBackButtonHighlight.visible = false;
LK.gui.center.addChild(languageBackButtonHighlight);
languageBackButtonHighlight.y = 145;
var languageBackText = new Text2('GERİ', {
size: 36,
fill: 0xFFFFFF
});
languageBackText.anchor.set(0.5, 0.5);
languageBackText.stroke = 0x566573;
languageBackText.strokeThickness = 2;
languageBackText.visible = false;
LK.gui.center.addChild(languageBackText);
languageBackText.y = 150;
// Function to show settings menu
function showSettingsMenu() {
// Remove and re-add settings overlay to bring it to front
LK.gui.center.removeChild(settingsOverlay);
LK.gui.center.addChild(settingsOverlay);
// Remove and re-add all settings elements to bring them to front
LK.gui.center.removeChild(settingsTitle);
LK.gui.center.addChild(settingsTitle);
LK.gui.center.removeChild(closeSettingsButton);
LK.gui.center.addChild(closeSettingsButton);
LK.gui.center.removeChild(closeSettingsText);
LK.gui.center.addChild(closeSettingsText);
LK.gui.center.removeChild(speedMenuButton);
LK.gui.center.addChild(speedMenuButton);
LK.gui.center.removeChild(speedMenuText);
LK.gui.center.addChild(speedMenuText);
LK.gui.center.removeChild(languageMenuButton);
LK.gui.center.addChild(languageMenuButton);
LK.gui.center.removeChild(languageMenuText);
LK.gui.center.addChild(languageMenuText);
settingsOverlay.visible = true;
settingsTitle.visible = true;
closeSettingsButton.visible = true;
closeSettingsButtonShadow.visible = true;
closeSettingsButtonHighlight.visible = true;
closeSettingsText.visible = true;
speedMenuButton.visible = true;
speedMenuButtonShadow.visible = true;
speedMenuButtonHighlight.visible = true;
speedMenuText.visible = true;
languageMenuButton.visible = true;
languageMenuButtonShadow.visible = true;
languageMenuButtonHighlight.visible = true;
languageMenuText.visible = true;
}
// Function to hide settings menu
function hideSettingsMenu() {
settingsOverlay.visible = false;
settingsTitle.visible = false;
closeSettingsButton.visible = false;
closeSettingsButtonShadow.visible = false;
closeSettingsButtonHighlight.visible = false;
closeSettingsText.visible = false;
speedMenuButton.visible = false;
speedMenuButtonShadow.visible = false;
speedMenuButtonHighlight.visible = false;
speedMenuText.visible = false;
languageMenuButton.visible = false;
languageMenuButtonShadow.visible = false;
languageMenuButtonHighlight.visible = false;
languageMenuText.visible = false;
hideSpeedControls();
hideLanguageControls();
}
// Function to show language controls
function showLanguageControls() {
// Hide speed controls first
hideSpeedControls();
// Hide language menu button
languageMenuButton.visible = false;
languageMenuText.visible = false;
// Remove and re-add language overlay to bring it to front
LK.gui.center.removeChild(languageOverlay);
LK.gui.center.addChild(languageOverlay);
// Remove and re-add all language elements to bring them to front
LK.gui.center.removeChild(languageTitle);
LK.gui.center.addChild(languageTitle);
LK.gui.center.removeChild(turkishButton);
LK.gui.center.addChild(turkishButton);
LK.gui.center.removeChild(turkishText);
LK.gui.center.addChild(turkishText);
LK.gui.center.removeChild(englishButton);
LK.gui.center.addChild(englishButton);
LK.gui.center.removeChild(englishText);
LK.gui.center.addChild(englishText);
LK.gui.center.removeChild(currentLanguageText);
LK.gui.center.addChild(currentLanguageText);
LK.gui.center.removeChild(languageBackButton);
LK.gui.center.addChild(languageBackButton);
LK.gui.center.removeChild(languageBackText);
LK.gui.center.addChild(languageBackText);
// Show language overlay and controls
languageOverlay.visible = true;
languageTitle.visible = true;
turkishButton.visible = true;
turkishButtonShadow.visible = true;
turkishButtonHighlight.visible = true;
turkishText.visible = true;
englishButton.visible = true;
englishButtonShadow.visible = true;
englishButtonHighlight.visible = true;
englishText.visible = true;
currentLanguageText.visible = true;
languageBackButton.visible = true;
languageBackButtonShadow.visible = true;
languageBackButtonHighlight.visible = true;
languageBackText.visible = true;
updateLanguageDisplay();
}
// Function to hide language controls
function hideLanguageControls() {
languageOverlay.visible = false;
languageTitle.visible = false;
turkishButton.visible = false;
turkishButtonShadow.visible = false;
turkishButtonHighlight.visible = false;
turkishText.visible = false;
englishButton.visible = false;
englishButtonShadow.visible = false;
englishButtonHighlight.visible = false;
englishText.visible = false;
currentLanguageText.visible = false;
languageBackButton.visible = false;
languageBackButtonShadow.visible = false;
languageBackButtonHighlight.visible = false;
languageBackText.visible = false;
// Show language menu button again if settings overlay is visible
if (settingsOverlay.visible) {
languageMenuButton.visible = true;
languageMenuButtonShadow.visible = true;
languageMenuButtonHighlight.visible = true;
languageMenuText.visible = true;
}
}
// Language text objects
var languageTexts = {
tr: {
mainTitle: 'FLAPPY BIRD',
playButton: 'OYNA',
instruction: 'TIKLA VE OYNA!',
gameOver: 'OYUN BİTTİ',
score: 'SKOR',
bestScore: 'EN İYİ',
retry: 'TEKRAR DENE',
mainMenu: 'ANA MENÜ',
settings: 'AYARLAR',
close: 'KAPAT',
speed: 'HIZ',
language: 'DİL',
speedTitle: 'HIZ AYARI',
languageTitle: 'DİL SEÇENEKLERİ',
normal: 'NORMAL',
current: 'MEVCUT',
highestScore: 'EN YÜKSEK',
back: 'GERİ'
},
en: {
mainTitle: 'FLAPPY BIRD',
playButton: 'PLAY',
instruction: 'CLICK TO PLAY!',
gameOver: 'GAME OVER',
score: 'SCORE',
bestScore: 'BEST',
retry: 'RETRY',
mainMenu: 'MAIN MENU',
settings: 'SETTINGS',
close: 'CLOSE',
speed: 'SPEED',
language: 'LANGUAGE',
speedTitle: 'SPEED SETTINGS',
languageTitle: 'LANGUAGE OPTIONS',
normal: 'NORMAL',
current: 'CURRENT',
highestScore: 'HIGHEST SCORE',
back: 'BACK'
}
};
// Function to get text for current language
function getText(key) {
return languageTexts[currentLanguage][key] || languageTexts['en'][key];
}
// Function to update all text elements to current language
function updateAllTexts() {
try {
// Main menu texts
if (instructionTxt && instructionTxt.setText) {
instructionTxt.setText(getText('instruction'));
// Use proper text sizing
var bgWidth = 400;
if (instructionTxt.width > bgWidth - 20) {
var newSize = Math.max(40, Math.floor(60 * (bgWidth - 20) / instructionTxt.width));
instructionTxt.style = {
size: newSize,
fill: instructionTxt.style.fill
};
}
}
// Update play button text
if (playButtonText && playButtonText.setText) {
playButtonText.setText(getText('playButton'));
// Use proper text sizing for play button
var playButtonWidth = 370;
if (playButtonText.width > playButtonWidth - 20) {
var newSize = Math.max(35, Math.floor(50 * (playButtonWidth - 20) / playButtonText.width));
playButtonText.style = {
size: newSize,
fill: playButtonText.style.fill
};
}
}
// Game over texts - always update these regardless of visibility
if (gameOverTitle && gameOverTitle.setText) gameOverTitle.setText(getText('gameOver'));
if (retryButtonText && retryButtonText.setText) {
retryButtonText.setText(getText('retry'));
// Use proper text sizing
var retryButtonWidth = 320;
if (retryButtonText.width > retryButtonWidth - 20) {
var newSize = Math.max(30, Math.floor(38 * (retryButtonWidth - 20) / retryButtonText.width));
retryButtonText.style = {
size: newSize,
fill: retryButtonText.style.fill
};
}
}
if (menuButtonText && menuButtonText.setText) {
menuButtonText.setText(getText('mainMenu'));
// Use proper text sizing
var menuButtonWidth = 320;
if (menuButtonText.width > menuButtonWidth - 20) {
var newSize = Math.max(30, Math.floor(38 * (menuButtonWidth - 20) / menuButtonText.width));
menuButtonText.style = {
size: newSize,
fill: menuButtonText.style.fill
};
}
}
// Settings texts
if (settingsTitle && settingsTitle.setText) settingsTitle.setText(getText('settings'));
if (closeSettingsText && closeSettingsText.setText) {
closeSettingsText.setText(getText('close'));
// Use proper text sizing
var closeButtonWidth = 240;
if (closeSettingsText.width > closeButtonWidth - 20) {
var newSize = Math.max(28, Math.floor(36 * (closeButtonWidth - 20) / closeSettingsText.width));
closeSettingsText.style = {
size: newSize,
fill: closeSettingsText.style.fill
};
}
}
if (speedMenuText && speedMenuText.setText) {
speedMenuText.setText(getText('speed'));
// Use proper text sizing
var speedMenuWidth = 320;
if (speedMenuText.width > speedMenuWidth - 20) {
var newSize = Math.max(32, Math.floor(42 * (speedMenuWidth - 20) / speedMenuText.width));
speedMenuText.style = {
size: newSize,
fill: speedMenuText.style.fill
};
}
}
if (languageMenuText && languageMenuText.setText) {
languageMenuText.setText(getText('language'));
// Use proper text sizing
var languageMenuWidth = 320;
if (languageMenuText.width > languageMenuWidth - 20) {
var newSize = Math.max(32, Math.floor(42 * (languageMenuWidth - 20) / languageMenuText.width));
languageMenuText.style = {
size: newSize,
fill: languageMenuText.style.fill
};
}
}
if (speedTitle && speedTitle.setText) speedTitle.setText(getText('speedTitle'));
if (languageTitle && languageTitle.setText) languageTitle.setText(getText('languageTitle'));
if (normalSpeedText && normalSpeedText.setText) {
normalSpeedText.setText(getText('normal'));
// Use proper text sizing
var normalSpeedWidth = 160;
if (normalSpeedText.width > normalSpeedWidth - 20) {
var newSize = Math.max(24, Math.floor(32 * (normalSpeedWidth - 20) / normalSpeedText.width));
normalSpeedText.style = {
size: newSize,
fill: normalSpeedText.style.fill
};
}
}
if (speedBackText && speedBackText.setText) {
speedBackText.setText(getText('back'));
// Use proper text sizing
var backButtonWidth = 200;
if (speedBackText.width > backButtonWidth - 20) {
var newSize = Math.max(28, Math.floor(36 * (backButtonWidth - 20) / speedBackText.width));
speedBackText.style = {
size: newSize,
fill: speedBackText.style.fill
};
}
}
if (languageBackText && languageBackText.setText) {
languageBackText.setText(getText('back'));
// Use proper text sizing
var langBackButtonWidth = 200;
if (languageBackText.width > langBackButtonWidth - 20) {
var newSize = Math.max(28, Math.floor(36 * (langBackButtonWidth - 20) / languageBackText.width));
languageBackText.style = {
size: newSize,
fill: languageBackText.style.fill
};
}
}
// Update current speed text with proper language
var speedText = getText('normal');
if (gameSpeed === 2) speedText = '2X';else if (gameSpeed === 1.5) speedText = '1.5X';else if (gameSpeed === 2.5) speedText = '2.5X';
if (currentSpeedText && currentSpeedText.setText) {
currentSpeedText.setText(getText('current') + ': ' + speedText);
// Use proper text sizing
if (currentSpeedText.width > 600) {
var newSize = Math.max(35, Math.floor(50 * 600 / currentSpeedText.width));
currentSpeedText.style = {
size: newSize,
fill: currentSpeedText.style.fill
};
}
}
// Update final and best score texts - always update these regardless of visibility
if (finalScoreText && finalScoreText.setText) {
var currentScore = LK.getScore();
finalScoreText.setText(getText('score') + ': ' + currentScore);
if (finalScoreText.width > 600) {
var newSize = Math.max(50, Math.floor(80 * 600 / finalScoreText.width));
finalScoreText.style = {
size: newSize,
fill: finalScoreText.style.fill
};
}
}
if (bestScoreText && bestScoreText.setText) {
var currentHighScore = _storage.highScore || 0;
bestScoreText.setText(getText('bestScore') + ': ' + currentHighScore);
if (bestScoreText.width > 600) {
var newSize = Math.max(40, Math.floor(60 * 600 / bestScoreText.width));
bestScoreText.style = {
size: newSize,
fill: bestScoreText.style.fill
};
}
}
} catch (e) {
console.log("Text update error:", e);
}
}
// Function to update language display
function updateLanguageDisplay() {
var langText = currentLanguage === 'tr' ? 'TÜRKÇE' : 'ENGLISH';
var currentText = currentLanguage === 'tr' ? 'MEVCUT' : 'CURRENT';
currentLanguageText.setText(currentText + ': ' + langText);
// Use proper text sizing
if (currentLanguageText.width > 600) {
var newSize = Math.max(35, Math.floor(50 * 600 / currentLanguageText.width));
currentLanguageText.style = {
size: newSize,
fill: currentLanguageText.style.fill
};
}
// Update button colors to show selected language
turkishButton.tint = currentLanguage === 'tr' ? 0x2ECC71 : 0x27AE60;
englishButton.tint = currentLanguage === 'en' ? 0x5DADE2 : 0x3498DB;
// Ensure language button texts fit properly
if (turkishText && turkishText.setText) {
turkishText.setText('TÜRKÇE');
var turkishButtonWidth = 240;
if (turkishText.width > turkishButtonWidth - 20) {
var newSize = Math.max(24, Math.floor(32 * (turkishButtonWidth - 20) / turkishText.width));
turkishText.style = {
size: newSize,
fill: turkishText.style.fill
};
}
}
if (englishText && englishText.setText) {
englishText.setText('ENGLISH');
var englishButtonWidth = 240;
if (englishText.width > englishButtonWidth - 20) {
var newSize = Math.max(24, Math.floor(32 * (englishButtonWidth - 20) / englishText.width));
englishText.style = {
size: newSize,
fill: englishText.style.fill
};
}
}
}
// Function to set language
function setLanguage(lang) {
currentLanguage = lang;
_storage.language = lang;
// Update all text elements immediately
updateAllTexts();
// Update language display
updateLanguageDisplay();
// Update speed display to use correct language
updateSpeedDisplay();
}
// Function to show speed controls
function showSpeedControls() {
// Hide language controls first
hideLanguageControls();
// Hide speed menu button
speedMenuButton.visible = false;
speedMenuText.visible = false;
// Remove and re-add speed overlay to bring it to front
LK.gui.center.removeChild(speedOverlay);
LK.gui.center.addChild(speedOverlay);
// Remove and re-add all speed elements to bring them to front
LK.gui.center.removeChild(speedTitle);
LK.gui.center.addChild(speedTitle);
LK.gui.center.removeChild(normalSpeedButton);
LK.gui.center.addChild(normalSpeedButton);
LK.gui.center.removeChild(normalSpeedText);
LK.gui.center.addChild(normalSpeedText);
LK.gui.center.removeChild(speed15xButton);
LK.gui.center.addChild(speed15xButton);
LK.gui.center.removeChild(speed15xText);
LK.gui.center.addChild(speed15xText);
LK.gui.center.removeChild(speed2xButton);
LK.gui.center.addChild(speed2xButton);
LK.gui.center.removeChild(speed2xText);
LK.gui.center.addChild(speed2xText);
LK.gui.center.removeChild(speed25xButton);
LK.gui.center.addChild(speed25xButton);
LK.gui.center.removeChild(speed25xText);
LK.gui.center.addChild(speed25xText);
LK.gui.center.removeChild(currentSpeedText);
LK.gui.center.addChild(currentSpeedText);
LK.gui.center.removeChild(speedBackButton);
LK.gui.center.addChild(speedBackButton);
LK.gui.center.removeChild(speedBackText);
LK.gui.center.addChild(speedBackText);
// Show speed overlay and controls
speedOverlay.visible = true;
speedTitle.visible = true;
normalSpeedButton.visible = true;
normalSpeedButtonShadow.visible = true;
normalSpeedButtonHighlight.visible = true;
normalSpeedText.visible = true;
speed15xButton.visible = true;
speed15xButtonShadow.visible = true;
speed15xButtonHighlight.visible = true;
speed15xText.visible = true;
speed2xButton.visible = true;
speed2xButtonShadow.visible = true;
speed2xButtonHighlight.visible = true;
speed2xText.visible = true;
speed25xButton.visible = true;
speed25xButtonShadow.visible = true;
speed25xButtonHighlight.visible = true;
speed25xText.visible = true;
currentSpeedText.visible = true;
speedBackButton.visible = true;
speedBackButtonShadow.visible = true;
speedBackButtonHighlight.visible = true;
speedBackText.visible = true;
updateSpeedDisplay();
}
// Function to hide speed controls
function hideSpeedControls() {
speedOverlay.visible = false;
speedTitle.visible = false;
normalSpeedButton.visible = false;
normalSpeedButtonShadow.visible = false;
normalSpeedButtonHighlight.visible = false;
normalSpeedText.visible = false;
speed2xButton.visible = false;
speed2xButtonShadow.visible = false;
speed2xButtonHighlight.visible = false;
speed2xText.visible = false;
speed25xButton.visible = false;
speed25xButtonShadow.visible = false;
speed25xButtonHighlight.visible = false;
speed25xText.visible = false;
speed15xButton.visible = false;
speed15xButtonShadow.visible = false;
speed15xButtonHighlight.visible = false;
speed15xText.visible = false;
currentSpeedText.visible = false;
speedBackButton.visible = false;
speedBackButtonShadow.visible = false;
speedBackButtonHighlight.visible = false;
speedBackText.visible = false;
// Show speed menu button again if settings overlay is visible
if (settingsOverlay.visible) {
speedMenuButton.visible = true;
speedMenuButtonShadow.visible = true;
speedMenuButtonHighlight.visible = true;
speedMenuText.visible = true;
}
}
// Function to update speed display
function updateSpeedDisplay() {
var speedText = getText('normal');
if (gameSpeed === 2) speedText = '2X';else if (gameSpeed === 1.5) speedText = '1.5X';else if (gameSpeed === 2.5) speedText = '2.5X';
currentSpeedText.setText(getText('current') + ': ' + speedText);
// Use proper text sizing
if (currentSpeedText.width > 600) {
var newSize = Math.max(35, Math.floor(50 * 600 / currentSpeedText.width));
currentSpeedText.style = {
size: newSize,
fill: currentSpeedText.style.fill
};
}
// Update button colors to show selected speed with more distinct colors
normalSpeedButton.tint = gameSpeed === 1 ? 0x1ABC9C : 0x27AE60; // Brighter teal when selected
speed2xButton.tint = gameSpeed === 2 ? 0xFF6B6B : 0xE74C3C; // Brighter red when selected
speed15xButton.tint = gameSpeed === 1.5 ? 0xFFE066 : 0xF39C12; // Brighter yellow when selected
speed25xButton.tint = gameSpeed === 2.5 ? 0xE91E63 : 0x9C27B0; // Brighter purple when selected
// Add subtle pulse animation to the selected button
if (gameSpeed === 1) {
tween(normalSpeedButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(normalSpeedButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
} else if (gameSpeed === 1.5) {
tween(speed15xButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(speed15xButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
} else if (gameSpeed === 2) {
tween(speed2xButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(speed2xButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
} else if (gameSpeed === 2.5) {
tween(speed25xButton, {
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(speed25xButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
}
// Ensure speed button texts fit properly and use correct language
if (normalSpeedText && normalSpeedText.setText) {
normalSpeedText.setText(getText('normal'));
var normalButtonWidth = 160;
if (normalSpeedText.width > normalButtonWidth - 20) {
var newSize = Math.max(24, Math.floor(32 * (normalButtonWidth - 20) / normalSpeedText.width));
normalSpeedText.style = {
size: newSize,
fill: normalSpeedText.style.fill
};
}
}
}
// Function to set game speed
function setGameSpeed(newSpeed) {
gameSpeed = newSpeed;
// Update dynamic spacing based on new speed
pipeSpacing = 500 + gameSpeed * 50;
updateSpeedDisplay();
// Update existing pipes if they exist
for (var i = 0; i < pipes.length; i++) {
if (pipes[i]) {
pipes[i].speed = basePipeSpeed * gameSpeed;
// Update gap size for existing pipes
pipes[i].gapSize = 750 + (gameSpeed - 1) * 50;
}
}
}
// Current language variable
var currentLanguage = 'tr'; // Default to Turkish
// Initialize local storage arrays if they don't exist
try {
// Use persistent storage directly
_storage = storage;
// Initialize arrays and values if they don't exist, but preserve existing values
if (!_storage.globalLeaderboardNames) _storage.globalLeaderboardNames = [];
if (!_storage.globalLeaderboardScores) _storage.globalLeaderboardScores = [];
if (typeof _storage.highScore === 'undefined') _storage.highScore = 0;
if (typeof _storage.lastScore === 'undefined') _storage.lastScore = 0;
if (!_storage.language) _storage.language = 'tr';
if (!_storage.username) _storage.username = 'Oyuncu1';
currentLanguage = _storage.language;
} catch (e) {
console.log("Storage initialization error:", e);
_storage = {
globalLeaderboardNames: [],
globalLeaderboardScores: [],
highScore: 0,
lastScore: 0,
language: 'tr',
username: 'Oyuncu1'
};
}
// Initialize username if not exists
if (!_storage.username) {
var playerNumber = 1;
while (_storage.globalLeaderboardNames.indexOf('Oyuncu ' + playerNumber) !== -1) {
playerNumber++;
}
_storage.username = 'Oyuncu ' + playerNumber;
}
// Create animated play button for main menu
var playButton = LK.getAsset('playButtonMain', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 120,
alpha: 1.0
});
playButton.tint = 0xFF9800; // Flappy Bird orange
try {
if (LK.gui && LK.gui.center) {
LK.gui.center.addChild(playButton);
playButton.y = -100;
}
} catch (e) {
console.log("Play button error:", e);
}
// Create separate play button shadow element
var playButtonShadow = LK.getAsset('playButtonShadow', {
anchorX: 0.5,
anchorY: 0.5,
width: 400,
height: 120,
alpha: 0.4
});
playButtonShadow.tint = 0xE65100; // Darker orange shadow
try {
if (LK.gui && LK.gui.center) {
LK.gui.center.addChild(playButtonShadow);
playButtonShadow.y = -92; // Offset shadow slightly up
playButtonShadow.x = 4; // Offset shadow slightly right
}
} catch (e) {
console.log("Play button shadow error:", e);
}
// Create separate play button highlight element
var playButtonHighlight = LK.getAsset('playButtonHighlight', {
anchorX: 0.5,
anchorY: 0.5,
width: 370,
height: 95,
alpha: 0.5
});
playButtonHighlight.tint = 0xFFB74D; // Lighter orange highlight
try {
if (LK.gui && LK.gui.center) {
LK.gui.center.addChild(playButtonHighlight);
playButtonHighlight.y = -108; // Offset highlight slightly down
}
} catch (e) {
console.log("Play button highlight error:", e);
}
// Create separate play button text element
var playButtonText = new Text2('OYNA', {
size: 50,
fill: 0xFFFFFF
});
playButtonText.anchor.set(0.5, 0.5);
playButtonText.stroke = 0xE65100;
playButtonText.strokeThickness = 4;
try {
if (LK.gui && LK.gui.center) {
LK.gui.center.addChild(playButtonText);
playButtonText.y = -100;
}
} catch (e) {
console.log("Play button text error:", e);
}
// Start continuous floating animation for play button
function startPlayButtonAnimation() {
if (playButton && playButton.parent) {
tween(playButton, {
y: -120,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (playButton && playButton.parent) {
tween(playButton, {
y: -80,
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (showMainMenu) {
startPlayButtonAnimation(); // Loop animation
}
}
});
}
}
});
}
// Animate shadow with slight delay
if (playButtonShadow && playButtonShadow.parent) {
tween(playButtonShadow, {
y: -112,
scaleX: 1.05,
scaleY: 1.05,
alpha: 0.3
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (playButtonShadow && playButtonShadow.parent) {
tween(playButtonShadow, {
y: -72,
scaleX: 0.95,
scaleY: 0.95,
alpha: 0.4
}, {
duration: 1500,
easing: tween.easeInOut
});
}
}
});
}
// Animate highlight with slight delay
if (playButtonHighlight && playButtonHighlight.parent) {
tween(playButtonHighlight, {
y: -128,
scaleX: 1.05,
scaleY: 1.05,
alpha: 0.4
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (playButtonHighlight && playButtonHighlight.parent) {
tween(playButtonHighlight, {
y: -88,
scaleX: 0.95,
scaleY: 0.95,
alpha: 0.5
}, {
duration: 1500,
easing: tween.easeInOut
});
}
}
});
}
// Animate text
if (playButtonText && playButtonText.parent) {
tween(playButtonText, {
y: -120,
scaleX: 1.05,
scaleY: 1.05
}, {
duration: 1500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (playButtonText && playButtonText.parent) {
tween(playButtonText, {
y: -80,
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 1500,
easing: tween.easeInOut
});
}
}
});
}
}
// Initialize game
resetGame(); // Use resetGame to properly initialize all states
// Update all texts to current language
updateAllTexts();
// Touch/click handler
game.down = function (x, y, obj) {
// Check settings button click - settings button is positioned at topRight with offset
var settingsX = 2048 - 80; // topRight.x + settingsButton.x offset
var settingsY = 80; // topRight.y + settingsButton.y offset
var settingsSize = 120; // Settings button size
if (x >= settingsX - settingsSize / 2 && x <= settingsX + settingsSize / 2 && y >= settingsY - settingsSize / 2 && y <= settingsY + settingsSize / 2) {
// Prevent rapid clicks
var currentTime;
try {
currentTime = Date.now ? Date.now() : new Date().getTime();
} catch (e) {
currentTime = 0;
}
if (currentTime - lastButtonClickTime < 500) {
return; // Ignore click if too recent
}
lastButtonClickTime = currentTime;
// Add visual feedback with tween for all settings button elements
tween(settingsButton, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
// Animate settings button shadow
tween(settingsButtonShadow, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 100
});
}
});
// Animate settings button highlight
tween(settingsButtonHighlight, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.6
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 100
});
}
});
// Animate settings icon
tween(settingsIcon, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(settingsIcon, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
showSettingsMenu();
return;
}
// Check close settings button if settings menu is open
if (settingsOverlay.visible) {
// Add invisible barriers between menu sections to prevent overlapping clicks
// Speed menu section barrier (between speed and language menus)
if (speedMenuButton.visible && !speedOverlay.visible && !languageOverlay.visible) {
// Check speed menu button (HIZ) with isolated click area
if (x >= 824 && x <= 1224 && y >= 1166 && y <= 1266) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(speedMenuButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(speedMenuButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
// Animate shadow and highlight for depth effect
tween(speedMenuButtonShadow, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(speedMenuButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 100
});
}
});
tween(speedMenuButtonHighlight, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.6
}, {
duration: 100,
onFinish: function onFinish() {
tween(speedMenuButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 100
});
}
});
showSpeedControls();
return;
}
// Barrier zone between speed and language buttons (y: 1266-1296)
if (y >= 1266 && y <= 1296) {
return; // Block clicks in the barrier zone
}
}
// Language menu section barrier
if (languageMenuButton.visible && !speedOverlay.visible && !languageOverlay.visible) {
// Check language menu button (DIL) with isolated click area
if (x >= 824 && x <= 1224 && y >= 1296 && y <= 1396) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(languageMenuButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(languageMenuButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
// Animate shadow and highlight for depth effect
tween(languageMenuButtonShadow, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(languageMenuButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 100
});
}
});
tween(languageMenuButtonHighlight, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.6
}, {
duration: 100,
onFinish: function onFinish() {
tween(languageMenuButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 100
});
}
});
showLanguageControls();
return;
}
}
// Language control buttons with barriers - only when language overlay is visible
if (languageOverlay.visible) {
// Turkish language button with isolated click area
if (turkishButton.visible && x >= 654 && x <= 954 && y >= 1246 && y <= 1326) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(turkishButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(turkishButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
setLanguage('tr');
return;
}
// Barrier zone between Turkish and English buttons (x: 954-1094)
if (x >= 954 && x <= 1094 && y >= 1246 && y <= 1326) {
return; // Block clicks in barrier zone
}
// English language button with isolated click area
if (englishButton.visible && x >= 1094 && x <= 1394 && y >= 1246 && y <= 1326) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(englishButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(englishButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
setLanguage('en');
return;
}
}
// Speed control buttons with barriers - only when speed overlay is visible
if (speedOverlay.visible) {
// Normal speed button with isolated click area
if (normalSpeedButton.visible && x >= 644 && x <= 844 && y >= 1246 && y <= 1326) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(normalSpeedButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(normalSpeedButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
setGameSpeed(1);
return;
}
// Barrier zone between normal and 1.5x buttons (x: 844-924)
if (x >= 844 && x <= 924 && y >= 1246 && y <= 1326) {
return; // Block clicks in barrier zone
}
// 1.5X speed button with isolated click area
if (speed15xButton.visible && x >= 924 && x <= 1124 && y >= 1246 && y <= 1326) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(speed15xButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(speed15xButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
setGameSpeed(1.5);
return;
}
// Barrier zone between 1.5x and 2x buttons (x: 1124-1164)
if (x >= 1124 && x <= 1164 && y >= 1246 && y <= 1326) {
return; // Block clicks in barrier zone
}
// 2X speed button with isolated click area
if (speed2xButton.visible && x >= 1164 && x <= 1344 && y >= 1246 && y <= 1326) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(speed2xButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(speed2xButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
setGameSpeed(2);
return;
}
// Barrier zone between 2x and 2.5x buttons (x: 1344-1384)
if (x >= 1344 && x <= 1384 && y >= 1246 && y <= 1326) {
return; // Block clicks in barrier zone
}
// 2.5X speed button with isolated click area
if (speed25xButton.visible && x >= 1384 && x <= 1564 && y >= 1246 && y <= 1326) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(speed25xButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(speed25xButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
setGameSpeed(2.5);
return;
}
}
// Check speed back button at x = 1024, y = 1516, size 300x100
if (speedBackButton.visible && x >= 874 && x <= 1174 && y >= 1466 && y <= 1566) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(speedBackButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(speedBackButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
hideSpeedControls();
return;
}
// Check language back button at x = 1024, y = 1516, size 300x100
if (languageBackButton.visible && x >= 874 && x <= 1174 && y >= 1466 && y <= 1566) {
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) return;
lastButtonClickTime = currentTime;
tween(languageBackButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(languageBackButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
hideLanguageControls();
return;
}
// Check close settings button (KAPAT) - centered at 1024x1516, button is 300x100
if (x >= 874 && x <= 1174 && y >= 1466 && y <= 1566) {
// Prevent rapid clicks
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) {
return; // Ignore click if too recent
}
lastButtonClickTime = currentTime;
// Add visual feedback with tween
tween(closeSettingsButton, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 100,
onFinish: function onFinish() {
tween(closeSettingsButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
}
});
// Animate shadow and highlight for depth effect
tween(closeSettingsButtonShadow, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(closeSettingsButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 100
});
}
});
tween(closeSettingsButtonHighlight, {
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.6
}, {
duration: 100,
onFinish: function onFinish() {
tween(closeSettingsButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 100
});
}
});
hideSettingsMenu();
return;
}
return; // Don't process other clicks when settings menu is open
}
// Check cup click - cup is positioned at bottomRight with offset
var cupX = 2048 - 100; // bottomRight.x + cupShape.x offset
var cupY = 2732 - 230; // bottomRight.y + cupShape.y offset
var cupSize = 120; // Cup asset size
if (x >= cupX - cupSize / 2 && x <= cupX + cupSize / 2 && y >= cupY && y <= cupY + cupSize) {
// Prevent rapid clicks
var currentTime;
try {
currentTime = Date.now ? Date.now() : new Date().getTime();
} catch (e) {
currentTime = 0;
}
if (currentTime - lastButtonClickTime < 500) {
return; // Ignore click if too recent
}
lastButtonClickTime = currentTime;
// Clear any existing high score displays first
var existingDisplays = LK.gui.center.children;
for (var k = existingDisplays.length - 1; k >= 0; k--) {
var child = existingDisplays[k];
if (child && child.getText && child.getText().indexOf('EN YÜKSEK:') !== -1) {
try {
child.destroy();
} catch (e) {
console.log("Error destroying high score display:", e);
}
}
}
// Clear any existing backgrounds
for (var k = existingDisplays.length - 1; k >= 0; k--) {
var child = existingDisplays[k];
if (child && child.tint === 0x000000 && child.width === 700) {
try {
child.destroy();
} catch (e) {
console.log("Error destroying background:", e);
}
}
}
// Show highest score in a temporary display using storage
var highScore = _storage && _storage.highScore || 0;
var highScoreDisplay = new Text2(getText('highestScore') + ': ' + highScore, {
size: 90,
fill: 0xFFFF00
});
highScoreDisplay.anchor.set(0.5, 0.5);
highScoreDisplay.stroke = 0x000000;
highScoreDisplay.strokeThickness = 4;
LK.gui.center.addChild(highScoreDisplay);
highScoreDisplay.y = -100;
// Add background for better visibility
var highScoreBg = LK.getAsset('barrier', {
anchorX: 0.5,
anchorY: 0.5,
width: 700,
height: 160,
alpha: 0.98
});
highScoreBg.tint = 0x000000;
LK.gui.center.addChild(highScoreBg);
highScoreBg.y = -100;
// Move background behind text
LK.gui.center.removeChild(highScoreBg);
LK.gui.center.addChildAt(highScoreBg, LK.gui.center.getChildIndex(highScoreDisplay));
// Auto-hide after 3 seconds
LK.setTimeout(function () {
try {
if (highScoreDisplay && highScoreDisplay.parent) {
highScoreDisplay.destroy();
}
if (highScoreBg && highScoreBg.parent) {
highScoreBg.destroy();
}
} catch (e) {
console.log("Error in timeout cleanup:", e);
}
}, 3000);
return;
}
if (gameOver || showGameOver) {
// Check retry button (TEKRAR DENE) - centered at 1024x1466, button is 380x110
if (x >= 834 && x <= 1214 && y >= 1411 && y <= 1521) {
// Prevent rapid clicks
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) {
return; // Ignore click if too recent
}
lastButtonClickTime = currentTime;
// Add enhanced visual feedback with tween
tween(retryButton, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(retryButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
// Animate shadow and highlight for depth effect
tween(retryButtonShadow, {
scaleX: 1.15,
scaleY: 1.15,
alpha: 0.5
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(retryButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
tween(retryButtonHighlight, {
scaleX: 1.15,
scaleY: 1.15,
alpha: 0.6
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(retryButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
hideGameOverScreen();
resetGame();
// Show instruction screen instead of starting game directly
startGameFromMenu();
return;
}
// Check menu button (ANA MENÜ) - centered at 1024x1616, button is 380x110
if (x >= 834 && x <= 1214 && y >= 1561 && y <= 1671) {
// Prevent rapid clicks
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) {
return; // Ignore click if too recent
}
lastButtonClickTime = currentTime;
// Add enhanced visual feedback with tween
tween(menuButton, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(menuButton, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
// Animate shadow and highlight for depth effect
tween(menuButtonShadow, {
scaleX: 1.15,
scaleY: 1.15,
alpha: 0.5
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(menuButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.3
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
tween(menuButtonHighlight, {
scaleX: 1.15,
scaleY: 1.15,
alpha: 0.6
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(menuButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
hideGameOverScreen();
resetGame();
return;
}
return;
}
if (showMainMenu) {
// Check play button click - centered at 1024x1266 (center.y = 1366 + playButton.y = -100), button is 400x120
if (playButton && playButton.visible && x >= 824 && x <= 1224 && y >= 1206 && y <= 1326) {
// Prevent rapid clicks
var currentTime = Date.now();
if (currentTime - lastButtonClickTime < 300) {
return; // Ignore click if too recent
}
lastButtonClickTime = currentTime;
// Enhanced click animation
tween(playButton, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFB74D
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playButton, {
scaleX: 1.0,
scaleY: 1.0,
tint: 0xFF9800
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
// Animate shadow
tween(playButtonShadow, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.6
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playButtonShadow, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.4
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
// Animate highlight
tween(playButtonHighlight, {
scaleX: 1.2,
scaleY: 1.2,
alpha: 0.8
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playButtonHighlight, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 0.5
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
// Animate text
tween(playButtonText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(playButtonText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.easeInOut
});
}
});
startGameFromMenu();
return;
}
return;
}
if (!gameStarted) {
gameStarted = true;
instructionTxt.visible = false;
// Remove invisible barriers when game starts
if (topBarrier) {
topBarrier.destroy();
topBarrier = null;
}
if (bottomBarrier) {
bottomBarrier.destroy();
bottomBarrier = null;
}
}
bird.flap();
};
// Main game loop
game.update = function () {
if (gameOver || showMainMenu || showGameOver) return;
// Only run game logic if game has started
if (gameStarted) {
// Check ground and ceiling collision with proper bird size (bird is 80px tall, 120px wide)
var birdRadius = 40; // Half of bird height for collision detection
if (bird.y + birdRadius >= 2732 - 150 || bird.y - birdRadius <= 0) {
gameOver = true;
var currentScore = LK.getScore();
_storage.lastScore = currentScore;
if (currentScore > (_storage.highScore || 0)) {
_storage.highScore = currentScore;
// High score is automatically saved to persistent storage via _storage reference
}
// Add to leaderboard if score > 0
if (currentScore > 0 && _storage) {
var currentUsername = _storage.username || 'Oyuncu';
var playerExists = false;
var leaderboardNames = _storage.globalLeaderboardNames || [];
for (var i = 0; i < leaderboardNames.length; i++) {
if (_storage.globalLeaderboardNames[i] === currentUsername) {
if (currentScore > _storage.globalLeaderboardScores[i]) {
_storage.globalLeaderboardScores[i] = currentScore;
}
playerExists = true;
break;
}
}
if (!playerExists) {
_storage.globalLeaderboardNames.push(currentUsername);
_storage.globalLeaderboardScores.push(currentScore);
}
}
showGameOverScreen(currentScore);
return;
}
// Check pipe collisions and scoring
for (var i = 0; i < pipes.length; i++) {
var pipe = pipes[i];
if (!pipe || !bird || pipe.destroyed || !pipe.parent) continue;
// Check scoring first - only for pipes that haven't been passed yet
if (!pipe.passed && pipe.x + 50 < bird.x) {
pipe.passed = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore().toString());
try {
var scoreSound = LK.getSound('score');
if (scoreSound && scoreSound.play) {
scoreSound.play();
}
} catch (e) {
console.log("Sound error:", e);
}
}
// Only check collision for pipes that are close to the bird
if (Math.abs(pipe.x - bird.x) < 150) {
// Check if bird is within pipe horizontally using actual pipe width
var pipeHalfWidth = (pipe.pipeWidth || 120) / 2;
if (bird.x + 40 > pipe.x - pipeHalfWidth && bird.x - 40 < pipe.x + pipeHalfWidth) {
// Check collision with top or bottom pipe - bird is 80px tall, so use 40px radius
var birdTop = bird.y - 40;
var birdBottom = bird.y + 40;
var gapTop = pipe.gapCenterY - pipe.gapSize / 2;
var gapBottom = pipe.gapCenterY + pipe.gapSize / 2;
// Collision occurs if bird overlaps with pipe (outside the gap)
if (birdTop < gapTop || birdBottom > gapBottom) {
gameOver = true;
var currentScore = LK.getScore();
_storage.lastScore = currentScore;
if (currentScore > (_storage.highScore || 0)) {
_storage.highScore = currentScore;
// High score is automatically saved to persistent storage via _storage reference
}
// Add to leaderboard if score > 0
if (currentScore > 0) {
var currentUsername = _storage.username;
var playerExists = false;
for (var j = 0; j < _storage.globalLeaderboardNames.length; j++) {
if (_storage.globalLeaderboardNames[j] === currentUsername) {
if (currentScore > _storage.globalLeaderboardScores[j]) {
_storage.globalLeaderboardScores[j] = currentScore;
}
playerExists = true;
break;
}
}
if (!playerExists) {
_storage.globalLeaderboardNames.push(currentUsername);
_storage.globalLeaderboardScores.push(currentScore);
}
}
showGameOverScreen(currentScore);
return;
}
}
}
}
// Create new pipes - maintain consistent spacing
if (pipes.length === 0 || pipes.length > 0 && pipes[pipes.length - 1].x <= 2048 + 100 - pipeSpacing) {
createPipe();
}
// Remove off-screen pipes periodically using frame counter
if (!game.frameCounter) game.frameCounter = 0;
game.frameCounter++;
if (game.frameCounter % 30 === 0) {
for (var j = pipes.length - 1; j >= 0; j--) {
if (pipes[j].x < -150) {
pipes[j].destroy();
pipes.splice(j, 1);
}
}
}
}
};