User prompt
Orjinal Tuğla Kırma Oyunundan Esinlenerek Level 6'yı Yap
User prompt
orjinal tuğla kırma oyunundan esinlenerek level 5'i yap
User prompt
orjinal tuğla kırma oyunundan esinlenerek level 4 ü de yap
User prompt
Oyunun level 3-ünü də tasarla orijinal tuğla qırma oyunundan əslənərək
User prompt
oyuna girdiğimizde yazan can kelimesi onu biraz sola çek
User prompt
Dili Seçtiğimizde Tüm Her Yer Aynı Şekilde Dil Değiştirme Uygulansın ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
DİL DEĞİŞTİRME DÜĞMELERİ KARE OLSUN
User prompt
Levellerin en üstünde dil değiştirme olsun, İngilizce ve Türkçe aynı şekilde ayarlar menüsünde de dil değiştirme olsun. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Ayarlar düğmesini kare yap
User prompt
ayarlar düğmesini biraz daha sola çek ve kare hale getir
User prompt
ayarlar düğmesini biraz daha sola çek
User prompt
ayarlar düğmesini biraz daha sola çek
User prompt
oyundaki hataları düzelt
User prompt
Level 1'in yanında sol tarafında ondan biraz ayrı ayarlar düğmesi olsun
User prompt
Canımız kaç kaldıysa canımız yazan kelimeyi sola kaydır ve 3 tane canımız varsa 3 tane kalp koy.
User prompt
oyuna başladığımızda biz hareket etmeden top hareket etmesin.
User prompt
tuğla kırıldığında ekrana gelen beyaz ışığı kapat sil
User prompt
tuğla kırıldığında ekrana streşim gelsin
User prompt
Level 3'ü orjinaline benzeterek oluştur
User prompt
Level'ler arası geçişi hatalarını düzelt
User prompt
Oyunu orjinal tuğla kırma oyununa benzet
User prompt
Level 2'yi de yap, orijinali gibi.
User prompt
Leveller arası geçiş yapmak için topumuz en üstteki boşluğa değmesi gerekir.
User prompt
Anladım, önceki cevabım genel bir seviye ilerleme mantığı üzerineydi. Şimdi, orijinal "Breakout" oyununun seviye tasarım prensiplerini ve zorluk artışını göz önünde bulundurarak, sizin tuğla kırma oyununuzun 30 seviyesini bu ruhla nasıl tasarlayacağınıza dair daha spesifik ve eksiksiz bir rehber sunuyorum. Orijinal oyunlar genellikle çok fazla levela sahip olmadığı için, 30 level için bu prensipleri genişleterek bir yol haritası oluşturacağız. Orijinal Oyun Prensibi: Orijinal Breakout'ta seviyeler, tuğlaların düzenleri ve bazen de tuğla dayanıklılıkları ile zorlaşır. Top hızı genellikle seviye ilerledikçe otomatik olarak artmaz, ancak vurulan tuğla sayısı veya belirli bir süre sonra hızlanabilir. Bizim durumumuzda, talep ettiğiniz üzere top hızını kademeli olarak artıracağız. Tuğla Kırma Oyunu: 30 Seviye Tasarım Rehberi (Orijinal Yaklaşımla Genişletilmiş) Genel Kurallar ve Mekanikler: * Tuğla Boyutu: Tüm tuğlalar, mevcut haliyle küçük olanların aksine, %50 daha büyük olmalıdır. * Kürek Boyutu: Oyuncunun platformu (kürek), genişliği %30 ve yüksekliği %20 artırılmış olmalıdır. * Top Boyutu: Topun çapı %40 artırılmış olmalıdır. * Top Hızı: Başlangıçta belirli bir hızda başlar. Her 5 seviyede bir top hızı biraz daha artırılabilir. (örn: Level 6, 11, 16, 21, 26'da top hızı %10 artar). Topun hızı zaten 2 katına çıkarılmıştı, bu artışlar onun üzerine eklenecek. * Can Sistemi: "Lives: 3" göstergesinin yanında kalp şeklinde bir logo olmalı. * Seviye İlerleme: Bir leveldeki tüm tuğlalar kırıldığında oyuncu otomatik olarak bir sonraki levele geçecek. Level 30 tamamlandığında oyunun bittiği kabul edilecek. * Level Menüsü: Oyun doğrudan level seçme menüsüyle başlayacak. Her sayfada 15 level gösterilecek ve sağ-sol ok tuşlarıyla sayfalar arası geçiş sağlanacak. Leveller kilitli olacak ve sadece önceki level tamamlandığında açılacak. Seviye Tasarımları (Örnekler ve Artan Zorluk): 1. AŞAMA: TEMELLER VE ALIŞMA (Seviye 1-5) * Tuğla Tipi: Hepsi tek vuruşluk standart tuğlalar. * Özellik: Güçlendirme (power-up) düşürmeyen tuğlalar. * Top Hızı: Başlangıç hızı. * Seviye 1: Sadece iki sıra halinde tuğlalar. Çok basit, oyuncunun topu ve küreği tanımasını sağlar. * Seviye 2: Üç sıra tuğla, tam ve düzenli diziliş. * Seviye 3: Dört sıra tuğla, tuğlalar arasında küçük yatay boşluklar olabilir. * Seviye 4: Beş sıra tuğla, basit bir dikdörtgen veya 'H' harfi gibi basit bir desen. * Seviye 5: Altı sıra tuğla, basit ama tam ekranı kaplayan bir blok. Top hızı biraz artırılabilir. 2. AŞAMA: YENİ TUĞLA TİPLERİ VE BASİT DESENLER (Seviye 6-10) * Tuğla Tipi: Tek vuruşluk tuğlaların yanı sıra, iki vuruşta kırılan tuğlalar (renk değiştirerek dayanıklılıklarını gösteren) tanıtılır. * Özellik: Hala güçlendirme düşmeyen tuğlalar. * Top Hızı: Seviye 6'da ilk hız artışı uygulanır. * Seviye 6: Üç sıra tek vuruşluk tuğla, ardından bir sıra iki vuruşluk tuğla. * Seviye 7: Beş sıra tuğla, köşelerde veya ortada iki vuruşluk tuğlalar. * Seviye 8: Tuğlalar arasında daha fazla boşluk olan bir 'U' veya 'L' şekli, iki vuruşluk tuğlalar stratejik noktalarda. * Seviye 9: Tuğlalar, topun geçişini zorlaştıran dikey sütunlar veya küçük kare bloklar halinde. Bazı iki vuruşluk tuğlalar arasına serpiştirilmiş. * Seviye 10: Karmaşık bir 'X' veya 'T' deseni, iki vuruşluk tuğlaların sayısı artırılır. Top hızı biraz artırılabilir. 3. AŞAMA: GELİŞMİŞ DESENLER VE ORTA DÜZEY ZORLUK (Seviye 11-15) * Tuğla Tipi: Tek ve iki vuruşluk tuğlaların kombinasyonları. Üç vuruşta kırılan tuğlalar tanıtılır (yine renk değiştirerek). * Özellik: Basit güçlendirmeler (örn: Küreği uzatan veya top hızını kısa süreliğine artıran) düşmeye başlayabilir. * Top Hızı: Seviye 11'de hız artışı uygulanır. * Seviye 11: Tuğlalar, topun sıkışabileceği dar koridorlar oluşturur. Üç vuruşluk tuğlalar ilk kez görünür. * Seviye 12: Birkaç sıra halinde üç vuruşluk tuğlaların oluşturduğu bir bariyer. * Seviye 13: Tuğlalar, topun sadece belirli açılardan erişebileceği şekilde yerleştirilmiş (örn: 'V' veya 'A' şeklinde). * Seviye 14: Ortada büyük bir boşluk bırakarak kenarlara dizilmiş tuğlalar. Bazı iki ve üç vuruşluk tuğlalar bu düzende stratejik olarak yerleştirilmiş. * Seviye 15: Ekranın büyük bir kısmını kaplayan, farklı dayanıklılıktaki tuğlaların karmaşık bir kafes deseni. Top hızı biraz artırılabilir. 4. AŞAMA: STRATEJİK YERLEŞİM VE YÜKSEK ZORLUK (Seviye 16-20) * Tuğla Tipi: Tek, iki, üç vuruşluk tuğlalar. Kırılamayan (geçici veya kalıcı) tuğlalar tanıtılır. * Özellik: Daha sık güçlendirme düşüşleri (çoklu top veya lazer atışı gibi). * Top Hızı: Seviye 16'da hız artışı uygulanır. * Seviye 16: Kırılamayan tuğlalar, kilit noktaları koruyan bariyerler oluşturur. * Seviye 17: Tuğlalar, topun hareket alanını kısıtlayan dar odacıklar veya tüneller şeklinde. * Seviye 18: Farklı renk ve dayanıklılıktaki tuğlalar, bir "piramit" veya "elmas" deseni oluşturur. Kırılamayan tuğlalar bu desene entegre edilmiş. * Seviye 19: Köşelerde veya kenarlarda kırılması zor olan tuğla kümeleri. * Seviye 20: Tuğlalar, sadece belirli açılardan veya güçlendirmelerle erişilebilen gizli alanlar oluşturur. Karmaşık ve topun seyahat edeceği alan daraltılmış bir desen. Top hızı biraz artırılabilir. 5. AŞAMA: UZMANLIK VE TEST (Seviye 21-25) * Tuğla Tipi: Tüm tuğla türleri (tek, iki, üç vuruşluk, kırılamayan). Dört vuruşta kırılan tuğlalar tanıtılır. * Özellik: Düşman nesneleri (topu saptıran veya can alan) veya hareketli tuğlalar tanıtılabilir (basit bir çizgide ileri geri hareket eden). * Top Hızı: Seviye 21'de hız artışı uygulanır. * Seviye 21: Ekranın büyük bir kısmını kaplayan, kırılamayan tuğlaların oluşturduğu karmaşık bir "labirent". Topun geçiş yolu çok dardır. * Seviye 22: Tuğlalar, topu sürekli olarak küreğe yönlendiren "tuzaklar" oluşturur. * Seviye 23: Çok sayıda üç ve dört vuruşluk tuğla, küçük ve dağınık gruplar halinde. * Seviye 24: Hem yatay hem dikey hareket eden tuğlalar içeren bir seviye. * Seviye 25: Oyuncunun tepki süresini test eden, çok hızlı top ve stratejik olarak yerleştirilmiş dayanıklı tuğlalar. Top hızı biraz artırılabilir. 6. AŞAMA: NİHAİ ZORLUK VE SON (Seviye 26-30) * Tuğla Tipi: Tüm tuğla türleri, maksimum dayanıklılık ve kırılamayan tuğlaların yoğun kullanımı. * Özellik: Topu yavaşlatan veya hızlandıran alanlar, ışınlanma (teleportasyon) noktaları veya topun hızını aniden artıran/azaltan özel tuğlalar gibi mekanikler eklenebilir. * Top Hızı: Seviye 26'da hız artışı uygulanır. * Seviye 26: Kırılamayan tuğlaların topun yolunu tamamen kapattığı, sadece belirli dar açılardan geçişe izin veren karmaşık desenler. * Seviye 27: Çok sayıda hareketli tuğla ile dinamik bir seviye. Oyuncunun hareketli hedefleri vurması gerekir. * Seviye 28: Tuğlaların çok dağınık ve küçük gruplar halinde olduğu, ancak her bir grubun yüksek dayanıklılığa sahip olduğu bir seviye. Topu onlara yönlendirmek çok zor. * Seviye 29: Ekranın üst kısmında çok sayıda kırılamayan tuğla ile çevrili, küçük bir alanda sıkışmış yüksek dayanıklılıklı tuğlalar. * Seviye 30 (Final Seviyesi): Tüm zorluk unsurlarının birleştiği, ekranın neredeyse tamamını kaplayan, farklı dayanıklılıktaki tuğlaların ve kırılamayan bariyerlerin olduğu, topun çok hızlı olduğu nihai bir test. Oyuncu bu seviyeyi bitirdiğinde büyük bir "TEBRİKLER!" mesajı ile karşılaşmalı. Bu detaylı seviye rehberi, oyunun 30 seviyesinin her birinin hem zorluk hem de görsel çeşitlilik açısından nasıl ilerleyeceğine dair kapsamlı bir çerçeve sunar. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Anladım, önceki cevabım genel bir seviye ilerleme mantığı üzerineydi. Şimdi, orijinal "Breakout" oyununun seviye tasarım prensiplerini ve zorluk artışını göz önünde bulundurarak, sizin tuğla kırma oyununuzun 30 seviyesini bu ruhla nasıl tasarlayacağınıza dair daha spesifik ve eksiksiz bir rehber sunuyorum. Orijinal oyunlar genellikle çok fazla levela sahip olmadığı için, 30 level için bu prensipleri genişleterek bir yol haritası oluşturacağız. Orijinal Oyun Prensibi: Orijinal Breakout'ta seviyeler, tuğlaların düzenleri ve bazen de tuğla dayanıklılıkları ile zorlaşır. Top hızı genellikle seviye ilerledikçe otomatik olarak artmaz, ancak vurulan tuğla sayısı veya belirli bir süre sonra hızlanabilir. Bizim durumumuzda, talep ettiğiniz üzere top hızını kademeli olarak artıracağız. Tuğla Kırma Oyunu: 30 Seviye Tasarım Rehberi (Orijinal Yaklaşımla Genişletilmiş) Genel Kurallar ve Mekanikler: * Tuğla Boyutu: Tüm tuğlalar, mevcut haliyle küçük olanların aksine, %50 daha büyük olmalıdır. * Kürek Boyutu: Oyuncunun platformu (kürek), genişliği %30 ve yüksekliği %20 artırılmış olmalıdır. * Top Boyutu: Topun çapı %40 artırılmış olmalıdır. * Top Hızı: Başlangıçta belirli bir hızda başlar. Her 5 seviyede bir top hızı biraz daha artırılabilir. (örn: Level 6, 11, 16, 21, 26'da top hızı %10 artar). Topun hızı zaten 2 katına çıkarılmıştı, bu artışlar onun üzerine eklenecek. * Can Sistemi: "Lives: 3" göstergesinin yanında kalp şeklinde bir logo olmalı. * Seviye İlerleme: Bir leveldeki tüm tuğlalar kırıldığında oyuncu otomatik olarak bir sonraki levele geçecek. Level 30 tamamlandığında oyunun bittiği kabul edilecek. * Level Menüsü: Oyun doğrudan level seçme menüsüyle başlayacak. Her sayfada 15 level gösterilecek ve sağ-sol ok tuşlarıyla sayfalar arası geçiş sağlanacak. Leveller kilitli olacak ve sadece önceki level tamamlandığında açılacak. Seviye Tasarımları (Örnekler ve Artan Zorluk): 1. AŞAMA: TEMELLER VE ALIŞMA (Seviye 1-5) * Tuğla Tipi: Hepsi tek vuruşluk standart tuğlalar. * Özellik: Güçlendirme (power-up) düşürmeyen tuğlalar. * Top Hızı: Başlangıç hızı. * Seviye 1: Sadece iki sıra halinde tuğlalar. Çok basit, oyuncunun topu ve küreği tanımasını sağlar. * Seviye 2: Üç sıra tuğla, tam ve düzenli diziliş. * Seviye 3: Dört sıra tuğla, tuğlalar arasında küçük yatay boşluklar olabilir. * Seviye 4: Beş sıra tuğla, basit bir dikdörtgen veya 'H' harfi gibi basit bir desen. * Seviye 5: Altı sıra tuğla, basit ama tam ekranı kaplayan bir blok. Top hızı biraz artırılabilir. 2. AŞAMA: YENİ TUĞLA TİPLERİ VE BASİT DESENLER (Seviye 6-10) * Tuğla Tipi: Tek vuruşluk tuğlaların yanı sıra, iki vuruşta kırılan tuğlalar (renk değiştirerek dayanıklılıklarını gösteren) tanıtılır. * Özellik: Hala güçlendirme düşmeyen tuğlalar. * Top Hızı: Seviye 6'da ilk hız artışı uygulanır. * Seviye 6: Üç sıra tek vuruşluk tuğla, ardından bir sıra iki vuruşluk tuğla. * Seviye 7: Beş sıra tuğla, köşelerde veya ortada iki vuruşluk tuğlalar. * Seviye 8: Tuğlalar arasında daha fazla boşluk olan bir 'U' veya 'L' şekli, iki vuruşluk tuğlalar stratejik noktalarda. * Seviye 9: Tuğlalar, topun geçişini zorlaştıran dikey sütunlar veya küçük kare bloklar halinde. Bazı iki vuruşluk tuğlalar arasına serpiştirilmiş. * Seviye 10: Karmaşık bir 'X' veya 'T' deseni, iki vuruşluk tuğlaların sayısı artırılır. Top hızı biraz artırılabilir. 3. AŞAMA: GELİŞMİŞ DESENLER VE ORTA DÜZEY ZORLUK (Seviye 11-15) * Tuğla Tipi: Tek ve iki vuruşluk tuğlaların kombinasyonları. Üç vuruşta kırılan tuğlalar tanıtılır (yine renk değiştirerek). * Özellik: Basit güçlendirmeler (örn: Küreği uzatan veya top hızını kısa süreliğine artıran) düşmeye başlayabilir. * Top Hızı: Seviye 11'de hız artışı uygulanır. * Seviye 11: Tuğlalar, topun sıkışabileceği dar koridorlar oluşturur. Üç vuruşluk tuğlalar ilk kez görünür. * Seviye 12: Birkaç sıra halinde üç vuruşluk tuğlaların oluşturduğu bir bariyer. * Seviye 13: Tuğlalar, topun sadece belirli açılardan erişebileceği şekilde yerleştirilmiş (örn: 'V' veya 'A' şeklinde). * Seviye 14: Ortada büyük bir boşluk bırakarak kenarlara dizilmiş tuğlalar. Bazı iki ve üç vuruşluk tuğlalar bu düzende stratejik olarak yerleştirilmiş. * Seviye 15: Ekranın büyük bir kısmını kaplayan, farklı dayanıklılıktaki tuğlaların karmaşık bir kafes deseni. Top hızı biraz artırılabilir. 4. AŞAMA: STRATEJİK YERLEŞİM VE YÜKSEK ZORLUK (Seviye 16-20) * Tuğla Tipi: Tek, iki, üç vuruşluk tuğlalar. Kırılamayan (geçici veya kalıcı) tuğlalar tanıtılır. * Özellik: Daha sık güçlendirme düşüşleri (çoklu top veya lazer atışı gibi). * Top Hızı: Seviye 16'da hız artışı uygulanır. * Seviye 16: Kırılamayan tuğlalar, kilit noktaları koruyan bariyerler oluşturur. * Seviye 17: Tuğlalar, topun hareket alanını kısıtlayan dar odacıklar veya tüneller şeklinde. * Seviye 18: Farklı renk ve dayanıklılıktaki tuğlalar, bir "piramit" veya "elmas" deseni oluşturur. Kırılamayan tuğlalar bu desene entegre edilmiş. * Seviye 19: Köşelerde veya kenarlarda kırılması zor olan tuğla kümeleri. * Seviye 20: Tuğlalar, sadece belirli açılardan veya güçlendirmelerle erişilebilen gizli alanlar oluşturur. Karmaşık ve topun seyahat edeceği alan daraltılmış bir desen. Top hızı biraz artırılabilir. 5. AŞAMA: UZMANLIK VE TEST (Seviye 21-25) * Tuğla Tipi: Tüm tuğla türleri (tek, iki, üç vuruşluk, kırılamayan). Dört vuruşta kırılan tuğlalar tanıtılır. * Özellik: Düşman nesneleri (topu saptıran veya can alan) veya hareketli tuğlalar tanıtılabilir (basit bir çizgide ileri geri hareket eden). * Top Hızı: Seviye 21'de hız artışı uygulanır. * Seviye 21: Ekranın büyük bir kısmını kaplayan, kırılamayan tuğlaların oluşturduğu karmaşık bir "labirent". Topun geçiş yolu çok dardır. * Seviye 22: Tuğlalar, topu sürekli olarak küreğe yönlendiren "tuzaklar" oluşturur. * Seviye 23: Çok sayıda üç ve dört vuruşluk tuğla, küçük ve dağınık gruplar halinde. * Seviye 24: Hem yatay hem dikey hareket eden tuğlalar içeren bir seviye. * Seviye 25: Oyuncunun tepki süresini test eden, çok hızlı top ve stratejik olarak yerleştirilmiş dayanıklı tuğlalar. Top hızı biraz artırılabilir. 6. AŞAMA: NİHAİ ZORLUK VE SON (Seviye 26-30) * Tuğla Tipi: Tüm tuğla türleri, maksimum dayanıklılık ve kırılamayan tuğlaların yoğun kullanımı. * Özellik: Topu yavaşlatan veya hızlandıran alanlar, ışınlanma (teleportasyon) noktaları veya topun hızını aniden artıran/azaltan özel tuğlalar gibi mekanikler eklenebilir. * Top Hızı: Seviye 26'da hız artışı uygulanır. * Seviye 26: Kırılamayan tuğlaların topun yolunu tamamen kapattığı, sadece belirli dar açılardan geçişe izin veren karmaşık desenler. * Seviye 27: Çok sayıda hareketli tuğla ile dinamik bir seviye. Oyuncunun hareketli hedefleri vurması gerekir. * Seviye 28: Tuğlaların çok dağınık ve küçük gruplar halinde olduğu, ancak her bir grubun yüksek dayanıklılığa sahip olduğu bir seviye. Topu onlara yönlendirmek çok zor. * Seviye 29: Ekranın üst kısmında çok sayıda kırılamayan tuğla ile çevrili, küçük bir alanda sıkışmış yüksek dayanıklılıklı tuğlalar. * Seviye 30 (Final Seviyesi): Tüm zorluk unsurlarının birleştiği, ekranın neredeyse tamamını kaplayan, farklı dayanıklılıktaki tuğlaların ve kırılamayan bariyerlerin olduğu, topun çok hızlı olduğu nihai bir test. Oyuncu bu seviyeyi bitirdiğinde büyük bir "TEBRİKLER!" mesajı ile karşılaşmalı. Bu detaylı seviye rehberi, oyunun 30 seviyesinin her birinin hem zorluk hem de görsel çeşitlilik açısından nasıl ilerleyeceğine dair kapsamlı bir çerçeve sunar. ↪💡 Consider importing and using the following plugins: @upit/storage.v1, @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 6; self.velocityY = -8; self.radius = 20; self.baseSpeed = 1.0; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; // Wall collision detection if (self.x - self.radius <= 0 || self.x + self.radius >= 2048) { self.velocityX = -self.velocityX; if (self.x - self.radius <= 0) self.x = self.radius; if (self.x + self.radius >= 2048) self.x = 2048 - self.radius; LK.getSound('hitWall').play(); } // Top wall collision if (self.y - self.radius <= 0) { self.velocityY = -self.velocityY; self.y = self.radius; LK.getSound('hitWall').play(); } }; return self; }); var Brick = Container.expand(function (brickType, hitPoints, isMoving) { var self = Container.call(this); var assetName = brickType || 'brick'; var brickGraphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.width = 225; self.height = 68; self.destroyed = false; self.hitPoints = hitPoints || 1; self.maxHitPoints = self.hitPoints; self.isMoving = isMoving || false; self.moveDirection = 1; self.moveSpeed = 1; self.moveRange = 200; self.startX = 0; self.originalTint = brickGraphics.tint; self.updateVisual = function () { if (self.hitPoints < self.maxHitPoints) { var alpha = 0.4 + self.hitPoints / self.maxHitPoints * 0.6; brickGraphics.alpha = alpha; } }; self.update = function () { if (self.isMoving && !self.destroyed) { if (Math.abs(self.x - self.startX) >= self.moveRange) { self.moveDirection *= -1; } self.x += self.moveDirection * self.moveSpeed; } }; return self; }); var LevelMenu = Container.expand(function () { var self = Container.call(this); self.currentPage = 0; self.levelsPerPage = 15; self.totalLevels = 30; self.unlockedLevel = storage.unlockedLevel || 1; var levelButtons = []; var leftArrow = null; var rightArrow = null; var pageText = null; self.createMenu = function () { // Create level buttons in 3 rows of 5 for (var i = 0; i < self.levelsPerPage; i++) { var row = Math.floor(i / 5); var col = i % 5; var button = new Container(); var buttonBg = button.attachAsset('brick', { anchorX: 0.5, anchorY: 0.5 }); var levelNum = new Text2('1', { size: 60, fill: 0xFFFFFF }); levelNum.anchor.set(0.5, 0.5); button.addChild(levelNum); button.x = 1024 + (col - 2) * 300; button.y = 800 + row * 200; button.levelIndex = i; button.levelText = levelNum; button.bg = buttonBg; button.down = function (x, y, obj) { var levelToStart = self.currentPage * self.levelsPerPage + this.levelIndex + 1; if (levelToStart <= self.unlockedLevel) { self.startLevel(levelToStart); } }; levelButtons.push(button); self.addChild(button); } // Create navigation arrows leftArrow = new Container(); var leftBg = leftArrow.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 2 }); var leftText = new Text2('<', { size: 120, fill: 0xFFFFFF }); leftText.anchor.set(0.5, 0.5); leftArrow.addChild(leftText); leftArrow.x = 300; leftArrow.y = 1000; leftArrow.down = function () { if (self.currentPage > 0) { self.currentPage--; self.updatePage(); } }; self.addChild(leftArrow); rightArrow = new Container(); var rightBg = rightArrow.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 2 }); var rightText = new Text2('>', { size: 120, fill: 0xFFFFFF }); rightText.anchor.set(0.5, 0.5); rightArrow.addChild(rightText); rightArrow.x = 1748; rightArrow.y = 1000; rightArrow.down = function () { var maxPages = Math.ceil(self.totalLevels / self.levelsPerPage); if (self.currentPage < maxPages - 1) { self.currentPage++; self.updatePage(); } }; self.addChild(rightArrow); // Create page indicator pageText = new Text2('Page 1 / 2', { size: 80, fill: 0xFFFFFF }); pageText.anchor.set(0.5, 0.5); pageText.x = 1024; pageText.y = 1400; self.addChild(pageText); self.updatePage(); }; self.updatePage = function () { var maxPages = Math.ceil(self.totalLevels / self.levelsPerPage); for (var i = 0; i < levelButtons.length; i++) { var levelNum = self.currentPage * self.levelsPerPage + i + 1; var button = levelButtons[i]; if (levelNum <= self.totalLevels) { button.levelText.setText(levelNum.toString()); button.visible = true; // Set button color based on unlock status if (levelNum <= self.unlockedLevel) { button.bg.tint = 0x00ff00; // Green for unlocked } else { button.bg.tint = 0xff0000; // Red for locked } } else { button.visible = false; } } // Update page text pageText.setText('Page ' + (self.currentPage + 1) + ' / ' + maxPages); // Update arrow visibility leftArrow.visible = self.currentPage > 0; rightArrow.visible = self.currentPage < maxPages - 1; }; self.startLevel = function (levelNumber) { currentLevel = levelNumber; self.destroy(); startGame(); }; return self; }); var Paddle = Container.expand(function () { var self = Container.call(this); var paddleGraphics = self.attachAsset('paddle', { anchorX: 0.5, anchorY: 0.5 }); self.width = 338; self.height = 29; self.powerUpActive = false; self.originalWidth = 338; return self; }); var PowerUp = Container.expand(function (powerType) { var self = Container.call(this); var powerGraphics = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.powerType = powerType; self.velocityY = 3; self.radius = 15; self.update = function () { self.y += self.velocityY; if (self.y > 2732) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ var currentLevel = 1; var gameStarted = false; var levelMenu = null; var powerUps = []; function generateLevelLayout(level) { var layouts = []; var brickConfigs = { basic: { type: 'brick', hits: 1 }, strong: { type: 'brickBlue', hits: 2 }, stronger: { type: 'brickGreen', hits: 3 }, strongest: { type: 'brickPurple', hits: 4 }, unbreakable: { type: 'brickUnbreakable', hits: -1 } }; // Levels 1-5: Basic introduction if (level <= 5) { var rows = 2 + level; for (var r = 0; r < rows; r++) { for (var c = 0; c < 8; c++) { layouts.push({ row: r, col: c, config: brickConfigs.basic }); } } } // Levels 6-10: Introduce 2-hit bricks else if (level <= 10) { var rows = 6; for (var r = 0; r < rows; r++) { for (var c = 0; c < 8; c++) { var config = r >= 3 ? brickConfigs.strong : brickConfigs.basic; layouts.push({ row: r, col: c, config: config }); } } } // Levels 11-15: Add 3-hit bricks and patterns else if (level <= 15) { var rows = 7; for (var r = 0; r < rows; r++) { for (var c = 0; c < 8; c++) { var config = brickConfigs.basic; if (r >= 5) config = brickConfigs.stronger;else if (r >= 3) config = brickConfigs.strong; if ((r + c) % 3 === 0) config = brickConfigs.stronger; layouts.push({ row: r, col: c, config: config }); } } } // Levels 16-20: Introduce unbreakable bricks else if (level <= 20) { var rows = 8; for (var r = 0; r < rows; r++) { for (var c = 0; c < 8; c++) { var config = brickConfigs.basic; if (r === 3 || r === 5) { if (c === 1 || c === 6) config = brickConfigs.unbreakable;else config = brickConfigs.stronger; } else if (r >= 6) { config = brickConfigs.strong; } layouts.push({ row: r, col: c, config: config }); } } } // Levels 21-25: Advanced patterns with moving bricks else if (level <= 25) { var rows = 8; for (var r = 0; r < rows; r++) { for (var c = 0; c < 8; c++) { var config = brickConfigs.basic; var isMoving = false; if (r === 2 && (c === 2 || c === 5)) { config = brickConfigs.strongest; isMoving = true; } else if (r >= 6) { config = brickConfigs.stronger; } else if (r >= 4) { config = brickConfigs.strong; } if (r === 1 && (c === 0 || c === 7)) config = brickConfigs.unbreakable; layouts.push({ row: r, col: c, config: config, moving: isMoving }); } } } // Levels 26-30: Final challenge levels else { var rows = 9; for (var r = 0; r < rows; r++) { for (var c = 0; c < 8; c++) { var config = brickConfigs.basic; var isMoving = false; if (r <= 1) { if ((c === 1 || c === 6) && r === 0) config = brickConfigs.unbreakable;else config = brickConfigs.strongest; } else if (r <= 3) { config = brickConfigs.stronger; if (c === 3 || c === 4) isMoving = true; } else if (r <= 6) { config = brickConfigs.strong; } else { config = brickConfigs.strongest; } if (level === 30 && r === 4 && c === 3) config = brickConfigs.unbreakable; layouts.push({ row: r, col: c, config: config, moving: isMoving }); } } } return layouts; } function getBallSpeedForLevel(level) { var speedMultiplier = 1.0; if (level >= 26) speedMultiplier = 1.5;else if (level >= 21) speedMultiplier = 1.4;else if (level >= 16) speedMultiplier = 1.3;else if (level >= 11) speedMultiplier = 1.2;else if (level >= 6) speedMultiplier = 1.1; return speedMultiplier; } var currentLevel = 1; var gameStarted = false; var levelMenu = null; var powerUps = []; // Initialize level menu first levelMenu = game.addChild(new LevelMenu()); levelMenu.createMenu(); var paddle = null; var ball = null; var bricks = []; var scoreTxt = null; var livesTxt = null; function startGame() { gameStarted = true; // Create paddle paddle = game.addChild(new Paddle()); paddle.x = 2048 / 2; paddle.y = 2600; // Create ball with level-appropriate speed ball = game.addChild(new Ball()); ball.x = 2048 / 2; ball.y = 2400; ball.baseSpeed = getBallSpeedForLevel(currentLevel); ball.velocityX *= ball.baseSpeed; ball.velocityY *= ball.baseSpeed; // Create bricks based on current level bricks = []; powerUps = []; var layoutData = generateLevelLayout(currentLevel); var cols = 8; var brickSpacingX = 240; var brickSpacingY = 85; var startX = (2048 - (cols - 1) * brickSpacingX) / 2; var startY = 200; for (var i = 0; i < layoutData.length; i++) { var data = layoutData[i]; var brick = new Brick(data.config.type, data.config.hits, data.moving); brick.x = startX + data.col * brickSpacingX; brick.y = startY + data.row * brickSpacingY; brick.startX = brick.x; if (data.config.hits > 0) { bricks.push(brick); game.addChild(brick); } } // Create UI elements scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); livesTxt = new Text2('Lives: 3', { size: 80, fill: 0xFFFFFF }); livesTxt.anchor.set(0, 0); livesTxt.x = -400; LK.gui.topRight.addChild(livesTxt); // Add heart icon next to lives text var heartIcon = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); heartIcon.x = -180; heartIcon.y = 40; LK.gui.topRight.addChild(heartIcon); // Reset game state lives = 3; LK.setScore(0); } var dragNode = null; var lastBallY = 0; function handleMove(x, y, obj) { if (!gameStarted) return; if (dragNode) { dragNode.x = x; // Keep paddle within screen bounds if (dragNode.x < dragNode.width / 2) { dragNode.x = dragNode.width / 2; } if (dragNode.x > 2048 - dragNode.width / 2) { dragNode.x = 2048 - dragNode.width / 2; } } } game.move = handleMove; game.down = function (x, y, obj) { if (!gameStarted) return; dragNode = paddle; handleMove(x, y, obj); }; game.up = function (x, y, obj) { if (!gameStarted) return; dragNode = null; }; function resetBall() { if (!ball) return; ball.x = 2048 / 2; ball.y = 2400; ball.velocityX = (Math.random() > 0.5 ? 1 : -1) * 6; ball.velocityY = -8; } function checkPaddleCollision() { if (!paddle || !ball) return; var paddleLeft = paddle.x - paddle.width / 2; var paddleRight = paddle.x + paddle.width / 2; var paddleTop = paddle.y - paddle.height / 2; var paddleBottom = paddle.y + paddle.height / 2; if (ball.x + ball.radius >= paddleLeft && ball.x - ball.radius <= paddleRight && ball.y + ball.radius >= paddleTop && ball.y - ball.radius <= paddleBottom && ball.velocityY > 0) { // Calculate hit position relative to paddle center (-1 to 1) var hitPos = (ball.x - paddle.x) / (paddle.width / 2); // Adjust ball velocity based on hit position ball.velocityX = hitPos * 5; ball.velocityY = -Math.abs(ball.velocityY); // Position ball above paddle ball.y = paddleTop - ball.radius; LK.getSound('hitPaddle').play(); } } function checkBrickCollisions() { if (!ball) return; for (var i = bricks.length - 1; i >= 0; i--) { var brick = bricks[i]; if (brick.destroyed || brick.hitPoints < 0) continue; var brickLeft = brick.x - brick.width / 2; var brickRight = brick.x + brick.width / 2; var brickTop = brick.y - brick.height / 2; var brickBottom = brick.y + brick.height / 2; if (ball.x + ball.radius >= brickLeft && ball.x - ball.radius <= brickRight && ball.y + ball.radius >= brickTop && ball.y - ball.radius <= brickBottom) { // Skip unbreakable bricks for collision response if (brick.hitPoints < 0) { // Determine collision side for unbreakable bricks var overlapLeft = ball.x + ball.radius - brickLeft; var overlapRight = brickRight - (ball.x - ball.radius); var overlapTop = ball.y + ball.radius - brickTop; var overlapBottom = brickBottom - (ball.y - ball.radius); var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom); if (minOverlap === overlapTop || minOverlap === overlapBottom) { ball.velocityY = -ball.velocityY; } else { ball.velocityX = -ball.velocityX; } LK.getSound('hitWall').play(); continue; } // Handle breakable bricks var overlapLeft = ball.x + ball.radius - brickLeft; var overlapRight = brickRight - (ball.x - ball.radius); var overlapTop = ball.y + ball.radius - brickTop; var overlapBottom = brickBottom - (ball.y - ball.radius); var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom); if (minOverlap === overlapTop || minOverlap === overlapBottom) { ball.velocityY = -ball.velocityY; } else { ball.velocityX = -ball.velocityX; } brick.hitPoints--; brick.updateVisual(); LK.getSound('hitBrick').play(); // Check if brick is destroyed if (brick.hitPoints <= 0) { // Chance to drop power-up if (Math.random() < 0.15 && currentLevel >= 11) { var powerUp = new PowerUp('extend'); powerUp.x = brick.x; powerUp.y = brick.y; powerUps.push(powerUp); game.addChild(powerUp); } brick.destroyed = true; brick.destroy(); bricks.splice(i, 1); LK.setScore(LK.getScore() + brick.maxHitPoints * 10); scoreTxt.setText('Score: ' + LK.getScore()); } // Check win condition if (bricks.length === 0) { // Unlock next level var unlockedLevel = storage.unlockedLevel || 1; if (currentLevel >= unlockedLevel && currentLevel < 30) { storage.unlockedLevel = currentLevel + 1; } // Check if all levels completed if (currentLevel >= 30) { // Show congratulations for completing all levels LK.showYouWin(); } else { // Auto-progress to next level currentLevel++; // Clear current game elements if (paddle) { paddle.destroy(); paddle = null; } if (ball) { ball.destroy(); ball = null; } for (var j = 0; j < bricks.length; j++) { if (bricks[j]) bricks[j].destroy(); } bricks = []; for (var k = 0; k < powerUps.length; k++) { if (powerUps[k]) powerUps[k].destroy(); } powerUps = []; if (scoreTxt) { scoreTxt.destroy(); scoreTxt = null; } if (livesTxt) { livesTxt.destroy(); livesTxt = null; } // Start next level after short delay LK.setTimeout(function () { startGame(); }, 1000); } } break; } } } game.update = function () { if (!gameStarted || !ball) return; // Check if ball fell below paddle if (lastBallY <= 2732 && ball.y > 2732) { lives--; livesTxt.setText('Lives: ' + lives); if (lives <= 0) { LK.showGameOver(); } else { resetBall(); } } // Check power-up collisions with paddle for (var p = powerUps.length - 1; p >= 0; p--) { var powerUp = powerUps[p]; if (powerUp.intersects(paddle)) { if (powerUp.powerType === 'extend') { paddle.width = paddle.originalWidth * 1.5; tween(paddle, { width: paddle.originalWidth }, { duration: 5000 }); } powerUp.destroy(); powerUps.splice(p, 1); } } checkPaddleCollision(); checkBrickCollisions(); lastBallY = ball.y; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 6;
self.velocityY = -8;
self.radius = 20;
self.baseSpeed = 1.0;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Wall collision detection
if (self.x - self.radius <= 0 || self.x + self.radius >= 2048) {
self.velocityX = -self.velocityX;
if (self.x - self.radius <= 0) self.x = self.radius;
if (self.x + self.radius >= 2048) self.x = 2048 - self.radius;
LK.getSound('hitWall').play();
}
// Top wall collision
if (self.y - self.radius <= 0) {
self.velocityY = -self.velocityY;
self.y = self.radius;
LK.getSound('hitWall').play();
}
};
return self;
});
var Brick = Container.expand(function (brickType, hitPoints, isMoving) {
var self = Container.call(this);
var assetName = brickType || 'brick';
var brickGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = 225;
self.height = 68;
self.destroyed = false;
self.hitPoints = hitPoints || 1;
self.maxHitPoints = self.hitPoints;
self.isMoving = isMoving || false;
self.moveDirection = 1;
self.moveSpeed = 1;
self.moveRange = 200;
self.startX = 0;
self.originalTint = brickGraphics.tint;
self.updateVisual = function () {
if (self.hitPoints < self.maxHitPoints) {
var alpha = 0.4 + self.hitPoints / self.maxHitPoints * 0.6;
brickGraphics.alpha = alpha;
}
};
self.update = function () {
if (self.isMoving && !self.destroyed) {
if (Math.abs(self.x - self.startX) >= self.moveRange) {
self.moveDirection *= -1;
}
self.x += self.moveDirection * self.moveSpeed;
}
};
return self;
});
var LevelMenu = Container.expand(function () {
var self = Container.call(this);
self.currentPage = 0;
self.levelsPerPage = 15;
self.totalLevels = 30;
self.unlockedLevel = storage.unlockedLevel || 1;
var levelButtons = [];
var leftArrow = null;
var rightArrow = null;
var pageText = null;
self.createMenu = function () {
// Create level buttons in 3 rows of 5
for (var i = 0; i < self.levelsPerPage; i++) {
var row = Math.floor(i / 5);
var col = i % 5;
var button = new Container();
var buttonBg = button.attachAsset('brick', {
anchorX: 0.5,
anchorY: 0.5
});
var levelNum = new Text2('1', {
size: 60,
fill: 0xFFFFFF
});
levelNum.anchor.set(0.5, 0.5);
button.addChild(levelNum);
button.x = 1024 + (col - 2) * 300;
button.y = 800 + row * 200;
button.levelIndex = i;
button.levelText = levelNum;
button.bg = buttonBg;
button.down = function (x, y, obj) {
var levelToStart = self.currentPage * self.levelsPerPage + this.levelIndex + 1;
if (levelToStart <= self.unlockedLevel) {
self.startLevel(levelToStart);
}
};
levelButtons.push(button);
self.addChild(button);
}
// Create navigation arrows
leftArrow = new Container();
var leftBg = leftArrow.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 2
});
var leftText = new Text2('<', {
size: 120,
fill: 0xFFFFFF
});
leftText.anchor.set(0.5, 0.5);
leftArrow.addChild(leftText);
leftArrow.x = 300;
leftArrow.y = 1000;
leftArrow.down = function () {
if (self.currentPage > 0) {
self.currentPage--;
self.updatePage();
}
};
self.addChild(leftArrow);
rightArrow = new Container();
var rightBg = rightArrow.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 2
});
var rightText = new Text2('>', {
size: 120,
fill: 0xFFFFFF
});
rightText.anchor.set(0.5, 0.5);
rightArrow.addChild(rightText);
rightArrow.x = 1748;
rightArrow.y = 1000;
rightArrow.down = function () {
var maxPages = Math.ceil(self.totalLevels / self.levelsPerPage);
if (self.currentPage < maxPages - 1) {
self.currentPage++;
self.updatePage();
}
};
self.addChild(rightArrow);
// Create page indicator
pageText = new Text2('Page 1 / 2', {
size: 80,
fill: 0xFFFFFF
});
pageText.anchor.set(0.5, 0.5);
pageText.x = 1024;
pageText.y = 1400;
self.addChild(pageText);
self.updatePage();
};
self.updatePage = function () {
var maxPages = Math.ceil(self.totalLevels / self.levelsPerPage);
for (var i = 0; i < levelButtons.length; i++) {
var levelNum = self.currentPage * self.levelsPerPage + i + 1;
var button = levelButtons[i];
if (levelNum <= self.totalLevels) {
button.levelText.setText(levelNum.toString());
button.visible = true;
// Set button color based on unlock status
if (levelNum <= self.unlockedLevel) {
button.bg.tint = 0x00ff00; // Green for unlocked
} else {
button.bg.tint = 0xff0000; // Red for locked
}
} else {
button.visible = false;
}
}
// Update page text
pageText.setText('Page ' + (self.currentPage + 1) + ' / ' + maxPages);
// Update arrow visibility
leftArrow.visible = self.currentPage > 0;
rightArrow.visible = self.currentPage < maxPages - 1;
};
self.startLevel = function (levelNumber) {
currentLevel = levelNumber;
self.destroy();
startGame();
};
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = 338;
self.height = 29;
self.powerUpActive = false;
self.originalWidth = 338;
return self;
});
var PowerUp = Container.expand(function (powerType) {
var self = Container.call(this);
var powerGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.powerType = powerType;
self.velocityY = 3;
self.radius = 15;
self.update = function () {
self.y += self.velocityY;
if (self.y > 2732) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
var currentLevel = 1;
var gameStarted = false;
var levelMenu = null;
var powerUps = [];
function generateLevelLayout(level) {
var layouts = [];
var brickConfigs = {
basic: {
type: 'brick',
hits: 1
},
strong: {
type: 'brickBlue',
hits: 2
},
stronger: {
type: 'brickGreen',
hits: 3
},
strongest: {
type: 'brickPurple',
hits: 4
},
unbreakable: {
type: 'brickUnbreakable',
hits: -1
}
};
// Levels 1-5: Basic introduction
if (level <= 5) {
var rows = 2 + level;
for (var r = 0; r < rows; r++) {
for (var c = 0; c < 8; c++) {
layouts.push({
row: r,
col: c,
config: brickConfigs.basic
});
}
}
}
// Levels 6-10: Introduce 2-hit bricks
else if (level <= 10) {
var rows = 6;
for (var r = 0; r < rows; r++) {
for (var c = 0; c < 8; c++) {
var config = r >= 3 ? brickConfigs.strong : brickConfigs.basic;
layouts.push({
row: r,
col: c,
config: config
});
}
}
}
// Levels 11-15: Add 3-hit bricks and patterns
else if (level <= 15) {
var rows = 7;
for (var r = 0; r < rows; r++) {
for (var c = 0; c < 8; c++) {
var config = brickConfigs.basic;
if (r >= 5) config = brickConfigs.stronger;else if (r >= 3) config = brickConfigs.strong;
if ((r + c) % 3 === 0) config = brickConfigs.stronger;
layouts.push({
row: r,
col: c,
config: config
});
}
}
}
// Levels 16-20: Introduce unbreakable bricks
else if (level <= 20) {
var rows = 8;
for (var r = 0; r < rows; r++) {
for (var c = 0; c < 8; c++) {
var config = brickConfigs.basic;
if (r === 3 || r === 5) {
if (c === 1 || c === 6) config = brickConfigs.unbreakable;else config = brickConfigs.stronger;
} else if (r >= 6) {
config = brickConfigs.strong;
}
layouts.push({
row: r,
col: c,
config: config
});
}
}
}
// Levels 21-25: Advanced patterns with moving bricks
else if (level <= 25) {
var rows = 8;
for (var r = 0; r < rows; r++) {
for (var c = 0; c < 8; c++) {
var config = brickConfigs.basic;
var isMoving = false;
if (r === 2 && (c === 2 || c === 5)) {
config = brickConfigs.strongest;
isMoving = true;
} else if (r >= 6) {
config = brickConfigs.stronger;
} else if (r >= 4) {
config = brickConfigs.strong;
}
if (r === 1 && (c === 0 || c === 7)) config = brickConfigs.unbreakable;
layouts.push({
row: r,
col: c,
config: config,
moving: isMoving
});
}
}
}
// Levels 26-30: Final challenge levels
else {
var rows = 9;
for (var r = 0; r < rows; r++) {
for (var c = 0; c < 8; c++) {
var config = brickConfigs.basic;
var isMoving = false;
if (r <= 1) {
if ((c === 1 || c === 6) && r === 0) config = brickConfigs.unbreakable;else config = brickConfigs.strongest;
} else if (r <= 3) {
config = brickConfigs.stronger;
if (c === 3 || c === 4) isMoving = true;
} else if (r <= 6) {
config = brickConfigs.strong;
} else {
config = brickConfigs.strongest;
}
if (level === 30 && r === 4 && c === 3) config = brickConfigs.unbreakable;
layouts.push({
row: r,
col: c,
config: config,
moving: isMoving
});
}
}
}
return layouts;
}
function getBallSpeedForLevel(level) {
var speedMultiplier = 1.0;
if (level >= 26) speedMultiplier = 1.5;else if (level >= 21) speedMultiplier = 1.4;else if (level >= 16) speedMultiplier = 1.3;else if (level >= 11) speedMultiplier = 1.2;else if (level >= 6) speedMultiplier = 1.1;
return speedMultiplier;
}
var currentLevel = 1;
var gameStarted = false;
var levelMenu = null;
var powerUps = [];
// Initialize level menu first
levelMenu = game.addChild(new LevelMenu());
levelMenu.createMenu();
var paddle = null;
var ball = null;
var bricks = [];
var scoreTxt = null;
var livesTxt = null;
function startGame() {
gameStarted = true;
// Create paddle
paddle = game.addChild(new Paddle());
paddle.x = 2048 / 2;
paddle.y = 2600;
// Create ball with level-appropriate speed
ball = game.addChild(new Ball());
ball.x = 2048 / 2;
ball.y = 2400;
ball.baseSpeed = getBallSpeedForLevel(currentLevel);
ball.velocityX *= ball.baseSpeed;
ball.velocityY *= ball.baseSpeed;
// Create bricks based on current level
bricks = [];
powerUps = [];
var layoutData = generateLevelLayout(currentLevel);
var cols = 8;
var brickSpacingX = 240;
var brickSpacingY = 85;
var startX = (2048 - (cols - 1) * brickSpacingX) / 2;
var startY = 200;
for (var i = 0; i < layoutData.length; i++) {
var data = layoutData[i];
var brick = new Brick(data.config.type, data.config.hits, data.moving);
brick.x = startX + data.col * brickSpacingX;
brick.y = startY + data.row * brickSpacingY;
brick.startX = brick.x;
if (data.config.hits > 0) {
bricks.push(brick);
game.addChild(brick);
}
}
// Create UI elements
scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
livesTxt = new Text2('Lives: 3', {
size: 80,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
livesTxt.x = -400;
LK.gui.topRight.addChild(livesTxt);
// Add heart icon next to lives text
var heartIcon = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heartIcon.x = -180;
heartIcon.y = 40;
LK.gui.topRight.addChild(heartIcon);
// Reset game state
lives = 3;
LK.setScore(0);
}
var dragNode = null;
var lastBallY = 0;
function handleMove(x, y, obj) {
if (!gameStarted) return;
if (dragNode) {
dragNode.x = x;
// Keep paddle within screen bounds
if (dragNode.x < dragNode.width / 2) {
dragNode.x = dragNode.width / 2;
}
if (dragNode.x > 2048 - dragNode.width / 2) {
dragNode.x = 2048 - dragNode.width / 2;
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (!gameStarted) return;
dragNode = paddle;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
if (!gameStarted) return;
dragNode = null;
};
function resetBall() {
if (!ball) return;
ball.x = 2048 / 2;
ball.y = 2400;
ball.velocityX = (Math.random() > 0.5 ? 1 : -1) * 6;
ball.velocityY = -8;
}
function checkPaddleCollision() {
if (!paddle || !ball) return;
var paddleLeft = paddle.x - paddle.width / 2;
var paddleRight = paddle.x + paddle.width / 2;
var paddleTop = paddle.y - paddle.height / 2;
var paddleBottom = paddle.y + paddle.height / 2;
if (ball.x + ball.radius >= paddleLeft && ball.x - ball.radius <= paddleRight && ball.y + ball.radius >= paddleTop && ball.y - ball.radius <= paddleBottom && ball.velocityY > 0) {
// Calculate hit position relative to paddle center (-1 to 1)
var hitPos = (ball.x - paddle.x) / (paddle.width / 2);
// Adjust ball velocity based on hit position
ball.velocityX = hitPos * 5;
ball.velocityY = -Math.abs(ball.velocityY);
// Position ball above paddle
ball.y = paddleTop - ball.radius;
LK.getSound('hitPaddle').play();
}
}
function checkBrickCollisions() {
if (!ball) return;
for (var i = bricks.length - 1; i >= 0; i--) {
var brick = bricks[i];
if (brick.destroyed || brick.hitPoints < 0) continue;
var brickLeft = brick.x - brick.width / 2;
var brickRight = brick.x + brick.width / 2;
var brickTop = brick.y - brick.height / 2;
var brickBottom = brick.y + brick.height / 2;
if (ball.x + ball.radius >= brickLeft && ball.x - ball.radius <= brickRight && ball.y + ball.radius >= brickTop && ball.y - ball.radius <= brickBottom) {
// Skip unbreakable bricks for collision response
if (brick.hitPoints < 0) {
// Determine collision side for unbreakable bricks
var overlapLeft = ball.x + ball.radius - brickLeft;
var overlapRight = brickRight - (ball.x - ball.radius);
var overlapTop = ball.y + ball.radius - brickTop;
var overlapBottom = brickBottom - (ball.y - ball.radius);
var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
if (minOverlap === overlapTop || minOverlap === overlapBottom) {
ball.velocityY = -ball.velocityY;
} else {
ball.velocityX = -ball.velocityX;
}
LK.getSound('hitWall').play();
continue;
}
// Handle breakable bricks
var overlapLeft = ball.x + ball.radius - brickLeft;
var overlapRight = brickRight - (ball.x - ball.radius);
var overlapTop = ball.y + ball.radius - brickTop;
var overlapBottom = brickBottom - (ball.y - ball.radius);
var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
if (minOverlap === overlapTop || minOverlap === overlapBottom) {
ball.velocityY = -ball.velocityY;
} else {
ball.velocityX = -ball.velocityX;
}
brick.hitPoints--;
brick.updateVisual();
LK.getSound('hitBrick').play();
// Check if brick is destroyed
if (brick.hitPoints <= 0) {
// Chance to drop power-up
if (Math.random() < 0.15 && currentLevel >= 11) {
var powerUp = new PowerUp('extend');
powerUp.x = brick.x;
powerUp.y = brick.y;
powerUps.push(powerUp);
game.addChild(powerUp);
}
brick.destroyed = true;
brick.destroy();
bricks.splice(i, 1);
LK.setScore(LK.getScore() + brick.maxHitPoints * 10);
scoreTxt.setText('Score: ' + LK.getScore());
}
// Check win condition
if (bricks.length === 0) {
// Unlock next level
var unlockedLevel = storage.unlockedLevel || 1;
if (currentLevel >= unlockedLevel && currentLevel < 30) {
storage.unlockedLevel = currentLevel + 1;
}
// Check if all levels completed
if (currentLevel >= 30) {
// Show congratulations for completing all levels
LK.showYouWin();
} else {
// Auto-progress to next level
currentLevel++;
// Clear current game elements
if (paddle) {
paddle.destroy();
paddle = null;
}
if (ball) {
ball.destroy();
ball = null;
}
for (var j = 0; j < bricks.length; j++) {
if (bricks[j]) bricks[j].destroy();
}
bricks = [];
for (var k = 0; k < powerUps.length; k++) {
if (powerUps[k]) powerUps[k].destroy();
}
powerUps = [];
if (scoreTxt) {
scoreTxt.destroy();
scoreTxt = null;
}
if (livesTxt) {
livesTxt.destroy();
livesTxt = null;
}
// Start next level after short delay
LK.setTimeout(function () {
startGame();
}, 1000);
}
}
break;
}
}
}
game.update = function () {
if (!gameStarted || !ball) return;
// Check if ball fell below paddle
if (lastBallY <= 2732 && ball.y > 2732) {
lives--;
livesTxt.setText('Lives: ' + lives);
if (lives <= 0) {
LK.showGameOver();
} else {
resetBall();
}
}
// Check power-up collisions with paddle
for (var p = powerUps.length - 1; p >= 0; p--) {
var powerUp = powerUps[p];
if (powerUp.intersects(paddle)) {
if (powerUp.powerType === 'extend') {
paddle.width = paddle.originalWidth * 1.5;
tween(paddle, {
width: paddle.originalWidth
}, {
duration: 5000
});
}
powerUp.destroy();
powerUps.splice(p, 1);
}
}
checkPaddleCollision();
checkBrickCollisions();
lastBallY = ball.y;
};