User prompt
Anladım. Flappy Bird oyununda hala görüntü hataları, skorlama ve oyun sonu mantığı ile ilgili sorunlar devam ediyor. Ayrıca bir skor tablosu da göremiyorum. Bu sorunları gidermek ve oyunu daha işlevsel hale getirmek için yapay zekaya daha detaylı ve öncelikli talimatlar veriyorum. Flappy Bird Oyunu: Görüntü Hataları, Skor, ve Oyun Sonu İyileştirmeleri 1. Görüntü Hataları (V2 Duvarı): * Sorun Tespiti: "Böyle görüntü hataları var V2 duvar arasında geçmemize rağmen puan vermek yerine öldürüyor." Ekranda belirsiz, "V2 duvarı" olarak tanımladığın bir görüntü hatası var ve bu hatayla temas puan almayı engelliyor ve hatta oyunu bitiriyor. * Düzeltme İsteği: * Hatalı Görsel Kaldırılmalı: Öncelikle bu "V2 duvarı" olarak adlandırdığın hatalı görseli tamamen ortadan kaldır. Oyunda sadece yeşil boru çiftleri olmalı. * Temiz Görsel Kontrolü: Oyunun tüm görsellerinin (kuş, borular, zemin, arka plan) temiz, net ve hatasız olduğundan emin ol. Herhangi bir piksel bozulması veya istenmeyen çizgi/şekil olmamalıdır. 2. Skorlama Mantığı: * Sorun Tespiti: "V2 duvar arasında geçmemize rağmen puan vermek yerine öldürüyor." Bu, skorlama ve çarpışma algılama mantığının birbiriyle karışmış olabileceğini gösteriyor. * Düzeltme İsteği: * Puanlama Koşulu: Skor, kuşun bir boru çiftinin üst ve alt borusu arasındaki boşluğu BAŞARIYLA tamamen geçtiği AN anlık olarak 1 puan artmalı. Puanlama, boru çifti ekrandan tamamen çıktıktan sonra değil, boşluk geçildiği anda yapılmalı. * Çarpışma Koşulu: Ölüm (oyun bitimi) sadece kuşun BORULARIN KENDİSİNE veya ZEMİNE çarpması durumunda gerçekleşmelidir. Hatalı "V2 duvarı" veya boşluklardan geçişler ölümle sonuçlanmamalıdır. 3. Oyun İçi Skor Göstergesi: * Yeni İstek: "Oyunu oynarken üst kısımda bir yerde skor gözüksün." Şu anda skor görünmüyor. * Uygulama İsteği: * Konum: Ekranın üst orta kısmında, arka plandan kolayca ayırt edilebilecek renkte (örneğin beyaz veya siyah), "SKOR: [Sayı]" formatında sürekli olarak güncellenen bir skor göstergesi ekle. Bu gösterge, oyun devam ederken oyuncunun mevcut skorunu anlık olarak göstermelidir. * Boyut ve Font: Skor yazısının boyutu okunabilir olmalı ancak oyun alanını çok fazla kapatmamalıdır. Sade ve anlaşılır bir font kullanılabilir. 4. Oyun Sonu Skor Ekranı: * Yeni İstek: "Oyun bitince de daha önce yaptığımız en yüksek skor ile bu el yaptığımız skor gözüksün." * Uygulama İsteği: Oyun bittikten sonra (kuş bir yere çarptığında): * "OYUN BİTTİ!" Mesajı: Ekranın ortasında belirgin bir şekilde "OYUN BİTTİ!" mesajı gösterilsin. * Mevcut Skor: Bu mesajın altında, "SKOR: [Bu Elki Skor]" şeklinde, bu oyunda elde edilen skor belirgin bir şekilde gösterilsin. * En Yüksek Skor: Onun da altında, "EN YÜKSEK SKOR: [Kaydedilen En Yüksek Skor]" şeklinde, oyuncunun daha önce elde ettiği en yüksek skor gösterilsin. * "Tekrar Oyna" ve "Ana Menüye Dön" Butonları: Bu bilgilerin altında, "Tekrar Oyna" ve "Ana Menüye Dön" butonları belirgin bir şekilde yer alsın. 5. En Yüksek Skorun Kaydedilmesi: * Yeni İstek: En yüksek skorun kaydedilmesi gerekiyor. * Uygulama İsteği: Oyun her bittiğinde, o anki skor, kaydedilmiş olan en yüksek skor ile karşılaştırılmalı. Eğer o anki skor daha yüksekse, en yüksek skor güncellenerek kaydedilmeli. Bu kayıt, oyun kapalıp açılsa bile saklanabilmelidir (yapay zekanın basit veri saklama yetenekleri dahilinde). Bu talimatlar, Flappy Bird oyunundaki temel oynanabilirlik sorunlarını çözmeyi ve istenen skorlama sistemini eklemeyi amaçlamaktadır. Özellikle "V2 duvarı" hatasının giderilmesi ve skorlama/çarpışma mantığının doğru bir şekilde uygulanması kritik önceliktir. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
duvarların arasından geçerken her bir duvarın arasından geçerken bir puan alıyoruz ve her aldığımız puan sonraki geçişimizde tekrar puan alıyoruz yani iki duvarın arasından geçerken bir puan alıyoruz
User prompt
Baştan da kaliteli Flappy Bird kuşu oluştur.
User prompt
Anladım, Flappy Bird oyunundaki takılma ve oyun bitirme mantığı sorunlarının hala devam ettiğini belirtiyorsun. Bu, önceki talimatlarımın tam olarak uygulanmadığı veya ek düzenlemelere ihtiyaç duyulduğu anlamına geliyor. Bu sorunları kesin olarak çözmek için, yapay zekaya daha keskin ve öncelikli talimatlar veriyorum. Flappy Bird Oyunu: Takılma ve Oyun Bitti Sorunları İçin Kesin Talimatlar **1. Performans Sorunu (Takılma/Donma) - Öncelik 1: Tamamen Ortadan Kaldırılmalı! * Sorun Tespiti: "Takılma hala az da olsa var." Bu, oyunun temel akışkanlığını etkiliyor ve kullanıcı deneyimi için kritik bir engel. * Çözüm Yolu (Kesin Talimat): * Tüm Görsel Değişimler Anında Olmalı: Kuşun zıplaması, yere düşmesi, boruların ve arka planın ilerlemesi gibi tüm görsel güncellemeler anında, milisaniyelik gecikme olmaksızın gerçekleşmelidir. Yapay zekanın "anlık görsel değişim" yeteneği bunu desteklemeli ve en ufak bir takılmaya izin vermemelidir. * Tıklama Tepkisi Gecikmesiz Olmalı: Oyuncu ekrana her tıkladığında, kuşun dikey konumu aynı anda, gecikmesiz bir şekilde yukarı doğru güncellenmelidir. Herhangi bir "sıraya alma" veya "işlem gecikmesi" olmamalıdır. Tıklama ile zıplama arasında hissedilebilir bir fark olmamalıdır. * Optimizasyon Kontrolü: İç algoritmaların, görsel güncellemeleri ve çarpışma kontrollerini en verimli şekilde işlediğinden emin ol. Bu, oyunun hızlı tempoya ayak uydurabilmesi için hayati önem taşır. Eğer bu performans seviyesi mevcut kısıtlamalarla (2D, anlık değişim) yapılabilecek en iyi seviyeyse, bana bu konuda açık bir geri bildirim vermen gerekiyor. **2. Oyun Bitirme Mantığı (Yere Düşünce Ölmemesi) - Öncelik 1: Mutlak Düzeltilmeli! * Sorun Tespiti: "Hala yere düşünce ölmüyor yani oyun bitmiyor." Bu, oyunun temel kuralını ve oynanabilirliğini doğrudan etkileyen bir hata. * Çözüm Yolu (Kesin Talimat): * Zemin Çarpışması Anında Tespit: Kuşun dikey konumu, zemin görselinin bulunduğu seviyeye ulaştığı AN, oyunun anında çarpışmayı algılaması ve tetiklemesi gerekmektedir. Burada hiçbir gecikme kabul edilemez. * Boru Çarpışması Anında Tespit: Benzer şekilde, kuşun konumu bir boru görselinin bulunduğu hücreyle herhangi bir anda çakıştığı AN, oyunun anında çarpışmayı algılaması ve tetiklemesi gerekmektedir. * Anında Oyun Durumu Değişikliği: Çarpışma (zemine veya boruya) tespit edildiği milisaniyede: * Oyun Durdurulmalı: Kuşun otomatik düşüşü, boruların ve arka planın yatay ilerlemesi hemen durmalıdır. Skor artışı da durmalıdır. * Mesaj Anında Belirmeli: "OYUN BİTTİ!" veya "ÇARPTIN!" mesajı, ekranın ortasında gecikme olmadan, anında belirmelidir. * Görsel Geri Bildirim: Kuşun görseli, çarptığı anda anlık olarak "hasarlı" veya "düşmüş" bir versiyonuna geçmeli veya rengi kısa bir an için kırmızıya dönmelidir. * Kontroller Devre Dışı: Oyun "bitti" durumuna geçtiği andan itibaren, oyuncunun ekrana yapacağı herhangi bir tıklama kesinlikle yok sayılmalı ve kuşun hareketini etkilememelidir. Sadece "Tekrar Oyna" ve "Ana Menüye Dön" butonları işlevsel kalmalıdır. Bu butonlar da oyun bittikten hemen sonra anında görünür olmalı ve tıklanabilir olmalıdır. Bu talimatlar, oyunun en temel mekanik sorunlarını çözmeye odaklanmıştır. Bu sorunların giderilmesi, diğer geliştirmelerden önce kesinlikle sağlanmalıdır.
User prompt
Anladım. Flappy Bird oyunundaki performans sorunları ve oyun sonu mantığındaki aksaklıkları düzeltmek için yapay zekaya daha net ve spesifik talimatlar veriyorum. Flappy Bird Oyunu Düzeltme ve İyileştirme Talimatları 1. Performans Sorunları (Kasma/Donma Düzeltmesi): * Sorun Tespiti: "Hızlı tıklayınca kasma donma oluyor." Bu, muhtemelen görsellerin anlık değişimi veya çarpışma algılama döngülerinin hızlı tıklamalarla senkronize olamamasından kaynaklanıyor. * Düzeltme İsteği: * Anlık Tepki Garantisi: Kullanıcı ekrana her tıkladığında, kuşun anında yukarı zıplamasını sağla. Hiçbir gecikme veya donma yaşanmamalıdır. * Optimal Görsel Geçiş Hızı: Arka plan ve boruların yatay ilerlemesi ile kuşun dikey hareketinin akıcıymış gibi hissettiren en stabil hızı bul ve bu hızda çalışmasını sağla. Aşırı hızlı değişimler kasma yapabilir. Bu, yapay zekanın sahip olduğu "anlık görsel değişim" yeteneğinin en verimli şekilde kullanılmasını gerektirir. * Kaynak Kullanımı Optimizasyonu: Eğer mümkünse, görsel değişimlerin ve çarpışma kontrollerinin işlemci üzerindeki yükünü minimuma indir. Bu, arka planda çalışan komutların daha verimli hale getirilmesi anlamına gelir. 2. Oyun Sonu Mantığı Düzeltmesi: * Sorun Tespiti: "Kuş yere çarpınca değil yere çarpıp bizim tıklamamızla beraber daha yeni oyun bitti diyor." Bu, oyunun bitiş anının yanlış zamanda tetiklendiği veya geri bildirimin geciktiği anlamına geliyor. * Düzeltme İsteği: * Anlık Çarpışma Tespiti: Kuşun zemine (yere) veya borulara çarptığı AN, çarpışma anlık olarak tespit edilsin. Bu tespitte hiçbir gecikme olmamalıdır. * Anında Oyun Bitti Durumu: Çarpışma tespit edildiği an, oyun hemen durmalı (kuşun hareketi, boruların ilerlemesi, skor artışı hepsi dursun). * Gecikmesiz Geri Bildirim: Oyunun durmasıyla eş zamanlı olarak ve gecikme olmadan "OYUN BİTTİ!" mesajı ekranda belirmelidir. Ayrıca kuşun görseli anında "düşmüş/hasarlı" versiyonuna geçmeli veya kısa bir an için rengi değişmelidir. * Tıklama Engellemesi: Oyun "bitti" durumuna geçtiği andan itibaren, oyuncunun ekrana yapacağı herhangi bir tıklama yok sayılmalı ve kuşun hareketini etkilememelidir. "Tekrar Oyna" veya "Ana Menüye Dön" butonları ise oyun bittikten hemen sonra görünür olmalı ve çalışmalıdır. Bu talimatlar, hem performans hem de oyun sonu mantığındaki temel sorunları gidermeyi hedeflemektedir. Yapay zekanın "anlık görsel değişim" ve "tıklama tabanlı etkileşim" yetenekleri bu düzeltmeler için anahtar olacaktır.
Code edit (1 edits merged)
Please save this source code
User prompt
Flappy Bird - Zıplayan Kuş
Initial prompt
Anladım! Ayrı ayrı geliştirdiğimiz prensibini koruyarak, Flappy Bird oyununu, yapay zekanın yetenek kısıtlamaları (2 boyutlu, anlık görsel değişimler, tıklama/basma tabanlı etkileşimler, akıcı animasyonlar veya kaydırma yok) dahilinde, tüm detaylarıyla sıfırdan tanımlıyorum. Modül Tanımı: 2 Boyutlu "Flappy Bird" Benzeri Oyun Bu modül, oyuncunun bir kuşu (veya benzeri bir karakteri) ekrana tıklayarak zıplatıp engellerden kaçırdığı, puan topladığı ve sonsuz bir ilerleme hissi veren basit bir beceri oyunudur. 1. Temel UI ve Oyun Alanı Tanımı * Ekran Boyutu: Oyun, açıldığında kendisine ayrılan ekran alanını tamamen kaplasın. * Arka Plan: Oyun alanı, sonsuz bir ilerleme illüzyonu vermek için yatay olarak sürekli "kayan" (aslında anlık olarak değişen) bir arka plana sahip olsun. * Görsel: Açık mavi bir gökyüzü (gündüz) veya koyu mavi/mor bir gece gökyüzü (gece modu için) gibi bir tema seçilebilir. * Detaylar: Uzakta sabit duran (ama oyun ilerledikçe değişen) bulutlar, dağlar, şehir siluetleri gibi öğeler ekleyebiliriz. Bunlar, ana arka plan görselinin bir parçası olarak anlık olarak değişerek ilerleme hissi verecektir. * Zemin/Yer: Ekranın en alt kısmında, karakterin üzerine düşebileceği, yeşil çim veya şehir yolu gibi sabit bir zemin görseli bulunsun. Karakter bu zemine çarptığında oyun biter. * Karakter (Kuş): * Görsel: Oyuncuyu temsil eden, yandan görünüşlü, sade ve sevimli 2 boyutlu bir kuş (veya top, kare gibi bir figür) görseli. Rengi, arka plandan ve borulardan belirgin bir şekilde ayrılsın (örneğin parlak sarı veya kırmızı). * Kanat Çırpma (Basit İllüzyon): Kuşun iki farklı statik kanat pozisyonu görseli olsun (kanatlar yukarıda ve kanatlar aşağıda). Oyuncu tıklama yaptığında, kuşun görseli anlık olarak kanatları yukarıda olan versiyona geçsin ve kısa bir süre sonra anlık olarak kanatları aşağıda olan versiyona geri dönsün. Bu, basit bir "çırpma" illüzyonu yaratır. * Konum: Kuş, ekranın sol orta kısmında, yatayda sabit bir konumda dursun. Sadece dikeyde (yukarı-aşağı) hareket edecek. * Borular/Engeller: * Görsel: Ekranın sağ tarafından sola doğru "gelen" (anlık olarak beliren ve değişen) dikey boru (veya sütun) çiftleri. Bu borular, ekranın üstünden ve altından gelerek ortalarında belirli bir geçiş boşluğu bırakır. Boruların rengi (örneğin yeşil veya metalik gri) ve dokusu olsun. * Oluşum: Boru çiftleri, ekranda belirli aralıklarla (örneğin her 2-3 saniyede bir) sağ taraftan anlık olarak belirsin ve sola doğru anlık olarak ilerleyerek (yani farklı boru segmenti görselleriyle değişerek) hareket illüzyonu yaratsın. * Boşluk: Her boru çiftinin ortasındaki boşluk dikeyde rastgele bir yükseklikte konumlandırılsın. Bu boşluğun boyutu sabit kalsın. 2. UI ve Göstergeler * Skor Paneli: Ekranın üst kısmında, ortalanmış, büyük ve okunabilir bir metin paneli bulunsun: "SKOR: [Miktar]" (başlangıçta SKOR: 0). * Puan Kazanımı: Kuş, bir boru çiftinin boşluğundan her başarılı geçtiğinde (yani boru çifti ekranın solundan tamamen çıktığında), skor anlık olarak artsın (örneğin her başarılı geçiş için 1 puan). * Oyun Durumu Mesajı: Oyun başladığında "Başlamak İçin Tıkla", çarpışma durumunda "OYUN BİTTİ!" gibi mesajları gösterecek boş bir metin alanı ekranın ortasında bulunabilir. 3. Kontrol Mekaniği ve İlerleme (Anlık Değişimler) * Karakter Kontrolü: * Tıklama/Basma: Oyuncu, ekrana herhangi bir yere tıklayabilir veya tek bir "Zıpla" düğmesine basabilir. * Zıplama: Her tıklamada, kuş anlık olarak belirli bir miktar yukarıya zıplasın (örneğin 3-4 hücre yukarı). * Yerçekimi: Kuş, tıklanmadığı sürece, sabit bir hızla anlık olarak aşağıya düşsün. Bu, her zamanlayıcı döngüsünde kuşun dikey konumunun anlık olarak birer birer azalmasıyla simüle edilir. * Oyunun İlerlemesi (Otomatik): * Arka plan ve borular, belirlediğimiz bir zaman aralığıyla (örneğin her 100-200 milisaniyede bir) otomatik olarak soldan sağa doğru anlık olarak ilerlesin. Bu, sürekli hareket ve sonsuz yol hissi yaratır. * İlerleme hızı, oyun ilerledikçe (belirli bir skora ulaşıldığında) anlık olarak artırılabilir (zorluk artışı). * Çarpışma Kontrolü (Anlık): * Boru Çarpışması: Kuşun konumu, bir boru görselinin bulunduğu bir hücreyle çakıştığında, çarpışma anlık olarak tespit edilsin. * Zemin Çarpışması: Kuşun dikey konumu, zemin seviyesine ulaştığında, çarpışma anlık olarak tespit edilsin. * Çarpışma Durumu: Çarpışma tespit edildiğinde: * Oyun Durumu Mesajı alanında "OYUN BİTTİ!" gibi bir mesaj anlık olarak belirtsin. * Skor paneli dursun. * Kuşun görseli anlık olarak "düşmüş" veya "hasar görmüş" bir versiyonuyla değişebilir. * Oyun dursun (ilerleme durur, tıklamalar işe yaramaz). 4. Oyun Sonlandırma ve Yeniden Başlatma * Oyun Bitti Ekranı: Oyun bittiğinde, oyun alanı ve kuş sabit kalsın. * Butonlar: Ekranın alt kısmında veya sonuç mesajının altında iki belirgin buton olsun: * "Tekrar Oyna" Butonu: Bu butona tıklanınca, oyun anlık olarak sıfırlansın, skor sıfırlansın, kuş başlangıç konumuna dönsün, yeni borular belirmeye başlasın ve yeni bir oyun başlasın. * "Ana Menüye Dön" Butonu: Bu butona tıklanınca, oyuncu anlık olarak telefon simülasyonunun ana ekranına geri dönsün. Bu detaylı tanım, Flappy Bird benzeri bir oyunu, yapay zekanın 2 boyutlu ve anlık değişim yetenekleriyle eksiksiz bir şekilde simüle etmesini sağlayacaktır. Akıcı animasyonlar yerine anlık görsel değişimlerle "zıplama", "kanat çırpma" ve "ilerleme" hissi yaratılacaktır.
/**** * 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);
}
}
}
}
};