User prompt
250 elmas ekle
User prompt
kullan butonuna basıldığında aktif gemiyi ship name yazan gemi ile değiştir
User prompt
kullan textini gemi ismi+kullan olarak değiştir
User prompt
satın aldan sonra çıkan kullan butonlarını gemi isimleri+kullan şeklinde getir
User prompt
elması 350 yap
User prompt
aynısını playership ile başlayan diğer gemilere de uygula
User prompt
kullan butonuna basıldığında aktif olan gemiyi playership2 ile değiştir
User prompt
playership2 yi kullan
User prompt
playership2 görselini playership2 için aktif et
User prompt
playership2 için mağazadan kullan aktif edildikten sonra oyunda playership2 görseli playership ile değişsin
User prompt
kullan butonuna tıklandığında ürün oyunda aktif geminin yerini alsın
User prompt
satın alma başarılı olduktan sonra fiyatı kaldır
User prompt
diamond sayacını 100 yap
User prompt
eğer mağazan ürün satın alımı başarılı olursa, satın al butonunun yerini kullan butonu alsın
User prompt
elmas sadece skorda görünsün bossu yenince otomatik kazanılsın
User prompt
elmas nesnesi ekranda gmörünmesin
User prompt
oyuna özgün mekanikler ekle
User prompt
enemtship2 tutarsız görünüyor
User prompt
gemi portaldan geçtikten sonra ekranda continius yazsın
User prompt
boss faz 2 iptal
User prompt
boss faz 2 için süre belirle
User prompt
enemyship2 ilk 20 düşman öldürüldükten sonra görünsün
User prompt
toplanan elmasları oyun kapatılmadıkça hafızada tut ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
oyunun en sonuna devam edecek yaz
User prompt
enemyship2 ye 2 mermi isabet ettiğinde ölsün
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScores: [] }); /**** * Classes ****/ // Asteroid - SAĞDAN SOLA var Asteroid = Container.expand(function () { var self = Container.call(this); var width = 120 + Math.random() * 60; var height = 120 + Math.random() * 60; var objAsset = self.attachAsset('spaceObject', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; objAsset.color = 0x888888; self.radius = width / 2; // Always spawn at right edge, random Y, move left self.x = 2048 + width; self.y = 200 + Math.random() * (2732 - 400); // Dynamic spawn effect: scale up and fade in self.scaleX = 0.6; self.scaleY = 0.6; self.alpha = 0.0; tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 400, easing: tween.easeOut }); // Speed will be set on spawn self.vx = -12; self.vy = (Math.random() - 0.5) * 2; self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Mermi (Bullet) - SAĞA DOĞRU var Bullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); // Asset: ellipse, width: 32, height: 32, color: 0xffe066 bulletAsset.width = 32; bulletAsset.height = 32; bulletAsset.color = 0xffe066; self.speed = typeof game !== "undefined" && game._bulletSpeedUp ? 38 : 22; // bulletspeed power-up aktifse daha hızlı, normalde biraz daha hızlı // Dynamic spawn effect: scale up and fade in self.scaleX = 0.5; self.scaleY = 0.5; self.alpha = 0.0; tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 200, easing: tween.easeOut }); self.update = function () { self.x += self.speed; }; return self; }); // EnemyBullet - DÜŞMAN MERMİSİ (sola doğru) var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('dusmanmermi', { anchorX: 0.5, anchorY: 0.5 }); bulletAsset.width = 32; bulletAsset.height = 32; bulletAsset.color = 0xff4444; self.speed = -16; // Sola doğru (daha hızlı) // Dynamic spawn effect: scale up and fade in self.scaleX = 0.5; self.scaleY = 0.5; self.alpha = 0.0; tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 200, easing: tween.easeOut }); self.update = function () { self.x += self.speed; }; return self; }); // EnemyShip - SAĞDAN SOLA var EnemyShip = Container.expand(function () { var self = Container.call(this); var width = 100; var height = 100; var objAsset = self.attachAsset('uzayNesnesi2', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; objAsset.color = 0xff4444; self.radius = width / 2; self.x = 2048 + width; self.y = 200 + Math.random() * (2732 - 400); // Dynamic spawn effect: scale up and fade in self.scaleX = 0.6; self.scaleY = 0.6; self.alpha = 0.0; tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 400, easing: tween.easeOut }); // Speed will be set on spawn self.vx = -14; self.vy = (Math.random() - 0.5) * 3; self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // MeteorStone - SAĞDAN SOLA, rastgele gelen düşman türü var MeteorStone = Container.expand(function () { var self = Container.call(this); var width = 120 + Math.random() * 60; var height = 120 + Math.random() * 60; var objAsset = self.attachAsset('meteorstone', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; self.radius = width / 2; // Always spawn at right edge, random Y, move left self.x = 2048 + width; self.y = 200 + Math.random() * (2732 - 400); // Dynamic spawn effect: scale up and fade in self.scaleX = 0.6; self.scaleY = 0.6; self.alpha = 0.0; tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 400, easing: tween.easeOut }); // Hız: asteroidlerden biraz daha hızlı olabilir var baseSpeed = 5 + Math.random() * 2.5; self.vx = -baseSpeed; self.vy = (Math.random() - 0.5) * 2.5; self.update = function () { // Oyuncu gemisi varsa ona doğru yönel if (typeof playerShip !== "undefined" && playerShip && typeof playerShip.x === "number" && typeof playerShip.y === "number") { var dx = playerShip.x - self.x; var dy = playerShip.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); // Hedefe doğru normalize edilmiş hız vektörü if (dist > 1) { var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy); // Hız sabit kalsın, sadece yön değişsin var nx = dx / dist; var ny = dy / dist; self.vx += (nx * speed - self.vx) * 0.08; // yumuşak yön değiştirme self.vy += (ny * speed - self.vy) * 0.08; } } self.x += self.vx; self.y += self.vy; }; return self; }); // Uzay Aracı (Player Ship) var PlayerShip = Container.expand(function () { var self = Container.call(this); // Ship asset: blue ellipse var shipAsset = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); // Asset will be created as: ellipse, width: 140, height: 100, color: 0x3a9cff shipAsset.width = 140; shipAsset.height = 100; shipAsset.color = 0x3a9cff; self.radius = 70; // For collision self.update = function () { // Otomatik sağa ilerleme kaldırıldı, sadece otomatik portal hareketi sırasında hareket etsin }; return self; }); // Uzay Cismi (Asteroid/Enemy) - SAĞDAN SOLA var SpaceObject = Container.expand(function () { var self = Container.call(this); // Randomly choose asteroid or enemy var isAsteroid = Math.random() < 0.7; var color = isAsteroid ? 0x888888 : 0xff4444; var width = isAsteroid ? 120 + Math.random() * 60 : 100; var height = isAsteroid ? 120 + Math.random() * 60 : 100; var objAsset = self.attachAsset('spaceObject', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; objAsset.color = color; self.radius = width / 2; // Always spawn at right edge, random Y, move left self.x = 2048 + width; self.y = 200 + Math.random() * (2732 - 400); // Dynamic spawn effect: scale up and fade in self.scaleX = 0.6; self.scaleY = 0.6; self.alpha = 0.0; tween(self, { scaleX: 1, scaleY: 1, alpha: 1 }, { duration: 400, easing: tween.easeOut }); var speed = 9 + Math.random() * 5; self.vx = -speed; self.vy = (Math.random() - 0.5) * 2; // hafif yukarı/aşağı varyasyon self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); /**** * Initialize Game ****/ // Create and add stars to the background var game = new LK.Game({ backgroundColor: 0x000010 }); /**** * Game Code ****/ // Galaksi arka planı kaldırıldı // Yıldızlar: Parallax ve hafif dönen yıldızlar var starBgCount = 90; var stars = []; var starBgContainer = new Container(); for (var i = 0; i < starBgCount; i++) { var starSize = 2 + Math.random() * 4; var star = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: Math.random() * 2048, y: Math.random() * 2732, width: starSize, height: starSize }); // Farklı parlaklıklar star.alpha = 0.3 + Math.random() * 0.7; // Farklı hızlar (parallax) star._vx = 0.7 + Math.random() * 1.2; // Hafif döndürme efekti star._rotSpeed = (Math.random() - 0.5) * 0.01; stars.push(star); starBgContainer.addChild(star); } game.addChild(starBgContainer); // Yıldız arka planı ekle (addChildAt yerine addChild ile, out of bounds hatasını önler) // --- BAŞLANGIÇ MENÜSÜ --- var startMenuContainer = new Container(); // Oyun başı intro sahnesi kaldırıldı, menü doğrudan gösteriliyor if (!startMenuContainer.parent) { startMenuContainer.alpha = 1; startMenuContainer.scaleX = 1; startMenuContainer.scaleY = 1; game.addChild(startMenuContainer); } // Menü renklerini dinamik olarak yönetmek için global değişkenler var menuBgColor = 0x181c2b; var menuButtonColors = [0x3a9cff, 0x4e5d94, 0x7cbb37, 0xf7b32b]; var menuWidth = 1000; var menuHeight = 1100; // Menü arka planına renkli kutu ekle (görsel yerine) var startMenuBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: menuWidth / 2, y: menuHeight / 2, width: menuWidth, height: menuHeight }); startMenuBg.alpha = 0.0; // Tamamen şeffaf yap startMenuBg.color = menuBgColor; startMenuContainer.addChild(startMenuBg); // Menü arka planına border efekti kaldırıldı (menu image ile uyumlu) // Başlık ve alt başlık var titleText = new Text2("UZAY MACERASI", { size: 120, fill: 0xFFE066 }); titleText.anchor.set(0.5, 0.5); titleText.x = menuWidth / 2; titleText.y = 140; startMenuContainer.addChild(titleText); // Subtitle text removed as requested // Dinamik butonlar var menuButtons = [{ label: "Yeni Oyun", key: "start", color: 0x3a9cff }, { label: "Mağaza", key: "options", color: 0x4e5d94 }, { label: "Rekorlar", key: "scores", color: 0x7cbb37 }, { label: "Hakkında", key: "about", color: 0xf7b32b }]; var buttonHeight = 140; var buttonWidth = 600; var buttonSpacing = 48; var firstBtnY = 400; var btnBgList = []; var btnTextList = []; for (var i = 0; i < menuButtons.length; i++) { var btnY = firstBtnY + i * (buttonHeight + buttonSpacing); // Butonun arka planı (hafif gölgeli, modern) var btnBgShadow = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: menuWidth / 2 + 8, y: btnY + 10, width: buttonWidth + 24, height: buttonHeight + 18 }); btnBgShadow.alpha = 0.18; btnBgShadow.color = 0x000000; startMenuContainer.addChild(btnBgShadow); var btnBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: menuWidth / 2, y: btnY, width: buttonWidth, height: buttonHeight }); btnBg.alpha = 0.92; btnBg.color = menuButtonColors[i % menuButtonColors.length]; btnBg.menuKey = menuButtons[i].key; btnBg.buttonIndex = i; btnBg.interactive = true; // Buton tıklanabilir olsun btnBg.defaultAlpha = btnBg.alpha; // Tıklama efekti için orijinal alpha btnBg.down = function (btn) { return function (x, y, obj) { // Tıklama efekti: sadece bu buton için kısa bir görsel geri bildirim uygula btn.alpha = 0.65; tween(btn, { alpha: btn.defaultAlpha }, { duration: 120 }); // Her butonun kendi işlevi if (btn.menuKey === "start") { // Menü animasyonla kaybolsun ve oyun başlasın tween(startMenuContainer, { alpha: 0, scaleX: 1.2, scaleY: 1.2 }, { duration: 350, onFinish: function onFinish() { if (startMenuContainer && startMenuContainer.parent) startMenuContainer.destroy(); // Oyun başladığında süreyi 3 dakikaya (180 saniye) sıfırla timeLeft = gameDuration; updateTimerDisplay(); gameStarted = true; } }); } else { // Her menü butonu için yeni bir ekran (modal) aç // Ana menü ekranını gizle if (startMenuContainer && startMenuContainer.parent) { startMenuContainer.visible = false; } var modalW = 1200; var modalH = 1000; var modalContainer = new Container(); var modalBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: modalH / 2, width: modalW, height: modalH }); modalBg.alpha = 0.0; // Tamamen şeffaf yap modalBg.color = 0x181c2b; modalContainer.addChild(modalBg); var modalTitle = ""; var modalContent = ""; if (btn.menuKey === "options") { modalTitle = "Mağaza"; modalContent = ""; // Satın alınabilir ürünler var storeProducts = []; // Ürünleri listele ve satın al butonları ekle var productBtnH = 110; var productBtnW = 600; var productBtnSpacing = 24; var firstProductY = 260; for (var p = 0; p < storeProducts.length; p++) { var prod = storeProducts[p]; var prodY = firstProductY + p * (productBtnH + productBtnSpacing); // Ürün kutusu var prodBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: prodY, width: productBtnW, height: productBtnH }); prodBg.alpha = 0.0; // Tamamen şeffaf yap prodBg.color = 0x232a3d; modalContainer.addChild(prodBg); // Ürün açıklaması (isim kaldırıldığı için üstte hizalanacak) var prodDesc = new Text2(prod.desc, { size: 36, fill: 0xB0E0FF, maxWidth: productBtnW - 220 }); // Açıklamayı butonun üstüne hizala prodDesc.anchor.set(0, 1); prodDesc.x = modalW / 2 - productBtnW / 2 + 32; prodDesc.y = prodY - productBtnH / 2 + 18; modalContainer.addChild(prodDesc); // Fiyat etiketi var priceTag = new Text2(prod.price + " 💎", { size: 44, fill: 0xFFE066 }); priceTag.anchor.set(1, 0.5); priceTag.x = modalW / 2 + productBtnW / 2 - 120; priceTag.y = prodY; modalContainer.addChild(priceTag); // Satın al butonu var buyBtn = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2 + productBtnW / 2 - 60, y: prodY, width: 100, height: 80 }); buyBtn.alpha = 0.85; buyBtn.color = 0x3a9cff; // Mavi ton, kırmızı arka plan kaldırıldı buyBtn.interactive = true; buyBtn.down = function (prod, buyBtnRef) { return function (x, y, obj) { // Satın alma işlemi (örnek: elmas bakiyesi yok, sadece görsel feedback) buyBtnRef.alpha = 0.65; tween(buyBtnRef, { alpha: 0.85 }, { duration: 120 }); // Satın alma bildirimi var boughtText = new Text2("Satın alındı!", { size: 44, fill: 0x7CBB37 }); boughtText.anchor.set(0.5, 0.5); boughtText.x = buyBtnRef.x; boughtText.y = buyBtnRef.y - 60; modalContainer.addChild(boughtText); tween(boughtText, { alpha: 0 }, { duration: 900, onFinish: function onFinish() { boughtText.destroy(); } }); }; }(prod, buyBtn); modalContainer.addChild(buyBtn); // Satın al butonu yazısı var buyBtnText = new Text2("Satın Al", { size: 36, fill: "#fff" }); buyBtnText.anchor.set(0.5, 0.5); buyBtnText.x = buyBtn.x; buyBtnText.y = buyBtn.y; buyBtnText.interactive = true; buyBtnText.down = function (buyBtnRef) { return function (x, y, obj) { if (buyBtnRef && buyBtnRef.down) buyBtnRef.down(x, y, obj); }; }(buyBtn); modalContainer.addChild(buyBtnText); } } else if (btn.menuKey === "scores") { modalTitle = "Rekorlar"; // --- High Scores Modal Content --- var scoresArr = getHighScores(); if (scoresArr.length === 0) { modalContent = "Henüz rekor yok!"; } else { modalContent = "En Yüksek 5 Skor:\n"; for (var s = 0; s < scoresArr.length; s++) { modalContent += s + 1 + ". " + scoresArr[s] + "\n"; } } } else if (btn.menuKey === "about") { modalTitle = "Hakkında"; modalContent = "Uzay Macerası - FRVR.Ava.Combo[POGAAS].v1.0"; } var modalTitleText = new Text2(modalTitle, { size: 100, fill: 0xFFE066, maxWidth: modalW - 80 // kutu kenarından taşmasın }); modalTitleText.anchor.set(0.5, 0.5); modalTitleText.x = modalW / 2; modalTitleText.y = 120; modalContainer.addChild(modalTitleText); // --- 3x3 Kare Slotlar: Mağaza başlığı ile kapat tuşu arasına --- // Sadece mağaza menüsünde slotlar görünsün if (btn.menuKey === "options") { // Kare slotlar için parametreler var slotSize = 280; // Daha büyük slotlar var slotSpacing = 64; // Slotlar arası biraz daha fazla boşluk var slotsPerRow = 3; var slotsPerCol = 1; // Artık sadece 1 satır olacak // Slotların başlık ile kapat tuşu arasında ortalanması ve kapat tuşu ile çakışmaması için Y konumunu ayarla // Kapat tuşu modalın en altında, slotlar başlığın hemen altından başlasın ve slotların altı ile kapat tuşu arasında yeterli boşluk kalsın var slotsTotalWidth = slotsPerRow * slotSize + (slotsPerRow - 1) * slotSpacing; var slotsTotalHeight = slotSize; // Sadece 1 satır var closeBtnH = 100; var closeBtnY = modalH - closeBtnH / 2 - 24; // Slotları modalın ortasına dikeyde ortala, başlık ile kapat tuşu arasında var availableHeight = closeBtnY - (modalTitleText.y + 120) - 40; var slotsStartY = modalTitleText.y + 120 + Math.max(0, (availableHeight - slotsTotalHeight) / 2); // Slotları yatayda tam merkeze hizala var slotsStartX = modalW / 2 - slotsTotalWidth / 2 + slotSize / 2; var slotList = []; for (var row = 0; row < slotsPerCol; row++) { for (var col = 0; col < slotsPerRow; col++) { var slotX = slotsStartX + col * (slotSize + slotSpacing); var slotY = slotsStartY + row * (slotSize + slotSpacing); var slot = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: slotX, y: slotY, width: slotSize, height: slotSize }); slot.alpha = 0.18; slot.color = 0xB0E0FF; modalContainer.addChild(slot); slotList.push(slot); // İlk slot ise playership2 görselini ortala ve sığdır if (row === 0 && col === 0) { // slotSize'ın %86'sı kadar bir kareye sığdır var ps2Margin = 0.07 * slotSize; var ps2Size = slotSize - 2 * ps2Margin; var ps2 = LK.getAsset('playership2', { anchorX: 0.5, anchorY: 0.5, x: slotX, y: slotY, width: ps2Size, height: ps2Size }); ps2.alpha = 1; modalContainer.addChild(ps2); } // 2. slot ise playership3 görselini ortala ve sığdır if (row === 0 && col === 1) { var ps3Margin = 0.07 * slotSize; var ps3Size = slotSize - 2 * ps3Margin; var ps3 = LK.getAsset('playership3', { anchorX: 0.5, anchorY: 0.5, x: slotX, y: slotY, width: ps3Size, height: ps3Size }); ps3.alpha = 1; modalContainer.addChild(ps3); } // Satın Al butonu ekle (her slotun altına) // Fiyat etiketleri: örnek olarak her slot için farklı fiyatlar var slotPrices = [100, 250, 0]; // 3. slot yakında olduğu için fiyat 0 var buyBtnW = 180; var buyBtnH = 90; var buyBtnY = slotY + slotSize / 2 + 44; var priceLabelY = buyBtnY + buyBtnH / 2 + 16; var price = slotPrices[col]; // Fiyat etiketi: Satın al butonunun hemen altına if (row === 0 && col === 2) { // 3. slotun satın al butonu pasif olsun var buyBtn = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: slotX, y: buyBtnY, width: buyBtnW, height: buyBtnH }); buyBtn.alpha = 0.45; buyBtn.color = 0x888888; buyBtn.interactive = false; // Butonun üstüne "Satın Al" yazısı (gri ve pasif) var buyBtnText = new Text2("Satın Al", { size: 32, fill: "#bbb" }); buyBtnText.anchor.set(0.5, 0.5); buyBtnText.x = buyBtn.x; buyBtnText.y = buyBtn.y; modalContainer.addChild(buyBtnText); // Fiyat etiketi (gri, pasif) var priceText = new Text2("-", { size: 28, fill: "#bbb" }); priceText.anchor.set(0.5, 0); priceText.x = slotX; priceText.y = priceLabelY; modalContainer.addChild(priceText); // 3. slotun altına "Yakında" yazısı ekle var yakindaText = new Text2("Yakında", { size: 32, fill: 0xFFE066 }); yakindaText.anchor.set(0.5, 0); yakindaText.x = slotX; yakindaText.y = priceLabelY + 38; modalContainer.addChild(yakindaText); } else { var buyBtn = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: slotX, y: buyBtnY, width: buyBtnW, height: buyBtnH }); buyBtn.alpha = 0.92; buyBtn.color = 0x3a9cff; buyBtn.interactive = true; buyBtn.defaultAlpha = buyBtn.alpha; buyBtn.down = function (btnRef, price) { return function (x, y, obj) { btnRef.alpha = 0.65; tween(btnRef, { alpha: btnRef.defaultAlpha }, { duration: 120 }); // Elmas kontrolü: yeterli elmas yoksa satın alma başarısız if (diamondCount < price) { var failText = new Text2("Yetersiz elmas!", { size: 36, fill: 0xf75b5b }); failText.anchor.set(0.5, 0.5); failText.x = btnRef.x; failText.y = btnRef.y - 48; modalContainer.addChild(failText); tween(failText, { alpha: 0 }, { duration: 900, onFinish: function onFinish() { failText.destroy(); } }); return; } // Elmasları harca diamondCount -= price; updateDiamondCounter(); // Satın alındı bildirimi var boughtText = new Text2("Satın alındı!", { size: 36, fill: 0x7CBB37 }); boughtText.anchor.set(0.5, 0.5); boughtText.x = btnRef.x; boughtText.y = btnRef.y - 48; modalContainer.addChild(boughtText); tween(boughtText, { alpha: 0 }, { duration: 900, onFinish: function onFinish() { boughtText.destroy(); } }); // Burada price değişkeni ile satın alma işlemi yapılabilir // Örn: satın alma işlemi için price değerini kullan }; }(buyBtn, price); modalContainer.addChild(buyBtn); // Butonun üstüne "Satın Al" yazısı var buyBtnText = new Text2("Satın Al", { size: 32, fill: "#fff" }); buyBtnText.anchor.set(0.5, 0.5); buyBtnText.x = buyBtn.x; buyBtnText.y = buyBtn.y; buyBtnText.interactive = true; buyBtnText.down = function (btnRef) { return function (x, y, obj) { if (btnRef && btnRef.down) btnRef.down(x, y, obj); }; }(buyBtn); modalContainer.addChild(buyBtnText); // Fiyat etiketi: Satın al butonunun hemen altına // Fiyat etiketi: sembolü + fiyat var priceText = new Text2("💎 " + price, { size: 38, fill: 0xFFE066 }); priceText.anchor.set(0.5, 0); priceText.x = slotX; priceText.y = priceLabelY + 24; modalContainer.addChild(priceText); } } } } var modalContentText = new Text2(modalContent, { size: 60, fill: "#fff", maxWidth: modalW - 80 // kutu kenarından taşmasın }); modalContentText.anchor.set(0.5, 0); // İçerik, slotların hemen altına gelsin ve slotlarla çakışmasın // Slotların altı ile kapat tuşu arasında yeterli boşluk bırak var contentMinY = slotsStartY + slotsPerCol * slotSize + (slotsPerCol - 1) * slotSpacing + 32; var contentMaxY = closeBtnY - closeBtnH / 2 - 40; modalContentText.y = Math.min(contentMinY, contentMaxY); modalContentText.x = modalW / 2; modalContainer.addChild(modalContentText); // Kapat butonu var closeBtnW = 320; var closeBtnH = 100; // Move close button to the very bottom of the modal var closeBtnY = modalH - closeBtnH / 2 - 24; // Modern gradient effect: use two overlapping containers with different colors and alpha for a faux-gradient var closeBtnBgBase = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: closeBtnY, width: closeBtnW, height: closeBtnH }); closeBtnBgBase.alpha = 0.95; closeBtnBgBase.color = 0x232a3d; // dark base modalContainer.addChild(closeBtnBgBase); var closeBtnBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: closeBtnY, width: closeBtnW, height: closeBtnH }); closeBtnBg.alpha = 0.92; closeBtnBg.color = 0x3a9cff; // blue overlay closeBtnBg.interactive = true; closeBtnBg.defaultAlpha = closeBtnBg.alpha; closeBtnBg.down = function () { return function (x, y, obj) { // Visual feedback: animate alpha closeBtnBg.alpha = 0.65; tween(closeBtnBg, { alpha: closeBtnBg.defaultAlpha }, { duration: 120 }); if (modalContainer && modalContainer.parent) modalContainer.destroy(); // Modal kapatıldığında ana menüyü tekrar göster if (startMenuContainer && !startMenuContainer.parent) { startMenuContainer.visible = true; game.addChild(startMenuContainer); } }; }(); modalContainer.addChild(closeBtnBg); // Dynamic hover/press highlight (top highlight) var closeBtnHighlight = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: closeBtnY - closeBtnH * 0.22, width: closeBtnW * 0.92, height: closeBtnH * 0.38 }); closeBtnHighlight.alpha = 0.18; closeBtnHighlight.color = 0xffffff; modalContainer.addChild(closeBtnHighlight); var closeBtnText = new Text2("Kapat", { size: 70, fill: "#fff", font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'" }); closeBtnText.anchor.set(0.5, 0.5); closeBtnText.x = modalW / 2; closeBtnText.y = closeBtnY; closeBtnText.interactive = true; closeBtnText.down = function (bgRef) { return function (x, y, obj) { if (bgRef && bgRef.down) bgRef.down(x, y, obj); }; }(closeBtnBg); modalContainer.addChild(closeBtnText); // Kapat butonu artık ana menüye döndürür closeBtnBg.down = function () { return function (x, y, obj) { if (modalContainer && modalContainer.parent) modalContainer.destroy(); // Modal kapatıldığında ana menüyü tekrar göster if (startMenuContainer) { startMenuContainer.visible = true; if (!startMenuContainer.parent) { game.addChild(startMenuContainer); } } }; }(); // Ortala ve ekrana ekle modalContainer.x = 2048 / 2 - modalW / 2; modalContainer.y = 2732 / 2 - modalH / 2; game.addChild(modalContainer); } }; }(btnBg); btnBgList.push(btnBg); startMenuContainer.addChild(btnBg); // Butonun üstüne hafif bir parlaklık efekti (degrade gibi) var btnHighlight = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: menuWidth / 2, y: btnY - buttonHeight / 3, width: buttonWidth * 0.92, height: buttonHeight * 0.38 }); btnHighlight.alpha = 0.18; btnHighlight.color = 0xffffff; startMenuContainer.addChild(btnHighlight); var btnText = new Text2(menuButtons[i].label, { size: 100, fill: "#fff", maxWidth: buttonWidth - 60 // buton kenarından taşmasın }); btnText.anchor.set(0.5, 0.5); btnText.x = menuWidth / 2; btnText.y = btnY; btnText.menuKey = menuButtons[i].key; btnText.buttonIndex = i; btnText.interactive = true; btnText.defaultAlpha = 1; btnText.down = function (btnBgRef, btnTextRef) { return function (x, y, obj) { // Text label dokunulduğunda kısa bir görsel geri bildirim uygula btnTextRef.alpha = 0.65; tween(btnTextRef, { alpha: btnTextRef.defaultAlpha }, { duration: 120 }); // Sadece kendi butonunun down fonksiyonunu tetikle if (btnBgRef && btnBgRef.down) { btnBgRef.down(x, y, obj); } }; }(btnBg, btnText); btnTextList.push(btnText); startMenuContainer.addChild(btnText); } // Bilgilendirici kısa açıklama var infoText = new Text2("Gemiyi sürükle, mermilerle uzay cisimlerini vur!", { size: 70, fill: "#fff", maxWidth: menuWidth - 80 // kutu kenarından taşmasın }); infoText.anchor.set(0.5, 0.5); infoText.x = menuWidth / 2; // Kırmızı bölümün altına hizala: kırmızı bölümün altı = startMenuBg.y + startMenuBg.height/2 infoText.y = startMenuBg.y + startMenuBg.height / 2 + 48; startMenuContainer.addChild(infoText); // Alt kısımda küçük bir imza var copyrightText = new Text2("© 2024 FRVR.Ava.Combo[POGAAS]", { size: 38, fill: 0xB0E0FF }); copyrightText.anchor.set(0.5, 0.5); copyrightText.x = menuWidth / 2; copyrightText.y = menuHeight - 32; startMenuContainer.addChild(copyrightText); // Ortala ve ekrana ekle startMenuContainer.x = 2048 / 2 - menuWidth / 2; startMenuContainer.y = 2732 / 2 - menuHeight / 2; // Oyun başında menü ekrana eklenmez, intro bitince eklenir // game.addChild(startMenuContainer); // Oyun başlamadan tüm kontrolleri ve update'i devre dışı bırak var gameStarted = false; // Ava: Dinamik duraklatma menüsü (Devam et, Yeniden başlat, Menü) var pauseMenuContainer = null; function showPauseMenu() { // Pause menu should not be shown in the main menu if (!gameStarted) return; if (pauseMenuContainer && pauseMenuContainer.parent) return; if (pauseMenuContainer) pauseMenuContainer.destroy(); var pauseMenuW = 800; var pauseMenuH = 700; pauseMenuContainer = new Container(); var pauseBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: pauseMenuW / 2, y: pauseMenuH / 2, width: pauseMenuW, height: pauseMenuH }); pauseBg.alpha = 0.0; // Tamamen şeffaf yap pauseBg.color = 0x181c2b; pauseMenuContainer.addChild(pauseBg); var pauseTitle = new Text2("Oyun Duraklatıldı", { size: 110, fill: 0xFFE066 }); pauseTitle.anchor.set(0.5, 0.5); pauseTitle.x = pauseMenuW / 2; pauseTitle.y = 140; pauseMenuContainer.addChild(pauseTitle); // Yeni seçenek menüsü: Oyun duraklatıldığında ekrana gelsin var optionsMenuButtons = [{ label: "Devam et", key: "resume", color: 0x3a9cff }, { label: "Yeniden başlat", key: "restart", color: 0x7cbb37 }, { label: "Menü", key: "menu", color: 0xf7b32b }, { label: "Ses Ayarları", key: "sound", color: 0x4e5d94 }, { label: "Yardım", key: "help", color: 0x9b59b6 }]; var pBtnH = 110; var pBtnW = 420; var pBtnSpacing = 28; var pFirstBtnY = 260; for (var i = 0; i < optionsMenuButtons.length; i++) { var pBtnY = pFirstBtnY + i * (pBtnH + pBtnSpacing); var pBtnBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: pauseMenuW / 2, y: pBtnY, width: pBtnW, height: pBtnH }); pBtnBg.alpha = 0.85; pBtnBg.color = optionsMenuButtons[i].color; pBtnBg.pauseKey = optionsMenuButtons[i].key; pBtnBg.defaultAlpha = pBtnBg.alpha; pBtnBg.interactive = true; pBtnBg.down = function (btn) { return function (x, y, obj) { btn.alpha = 0.65; tween(btn, { alpha: btn.defaultAlpha }, { duration: 120 }); if (btn.pauseKey === "resume") { // Devam et: menüyü kapat, oyuna devam et if (pauseMenuContainer && pauseMenuContainer.parent) pauseMenuContainer.destroy(); gameStarted = true; } else if (btn.pauseKey === "restart") { // Yeniden başlat: oyunu baştan başlat LK.restartGame(); } else if (btn.pauseKey === "menu") { // Menü: ana menüyü göster, pause menüsünü kapat if (pauseMenuContainer && pauseMenuContainer.parent) pauseMenuContainer.destroy(); showMenu(); } else if (btn.pauseKey === "sound") { // Ses ayarları: yeni bir modal aç var modalW = 700; var modalH = 400; var modalContainer = new Container(); var modalBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: modalH / 2, width: modalW, height: modalH }); modalBg.alpha = 0.0; // Tamamen şeffaf yap modalBg.color = 0x181c2b; modalContainer.addChild(modalBg); var modalTitle = new Text2("Ses Ayarları", { size: 80, fill: 0xFFE066, maxWidth: modalW - 60 }); modalTitle.anchor.set(0.5, 0.5); modalTitle.x = modalW / 2; modalTitle.y = 80; modalContainer.addChild(modalTitle); var modalContent = new Text2("Ses ayarları burada olacak.", { size: 50, fill: "#fff", maxWidth: modalW - 60 }); modalContent.anchor.set(0.5, 0); modalContent.x = modalW / 2; modalContent.y = 160; modalContainer.addChild(modalContent); // Kapat butonu var closeBtnW = 220; var closeBtnH = 80; var closeBtnY = modalH - 80; var closeBtnBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: closeBtnY, width: closeBtnW, height: closeBtnH }); closeBtnBg.alpha = 0.85; closeBtnBg.color = 0x3a9cff; closeBtnBg.interactive = true; closeBtnBg.down = function () { return function (x, y, obj) { if (modalContainer && modalContainer.parent) modalContainer.destroy(); }; }(); modalContainer.addChild(closeBtnBg); var closeBtnText = new Text2("Kapat", { size: 60, fill: "#fff", font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'" // Modern font stack }); closeBtnText.anchor.set(0.5, 0.5); closeBtnText.x = modalW / 2; closeBtnText.y = closeBtnY; closeBtnText.interactive = true; closeBtnText.down = function (bgRef) { return function (x, y, obj) { if (bgRef && bgRef.down) bgRef.down(x, y, obj); }; }(closeBtnBg); modalContainer.addChild(closeBtnText); // Ortala ve ekrana ekle modalContainer.x = 2048 / 2 - modalW / 2; modalContainer.y = 2732 / 2 - modalH / 2; game.addChild(modalContainer); } else if (btn.pauseKey === "help") { // Yardım: yeni bir modal aç var modalW = 700; var modalH = 400; var modalContainer = new Container(); var modalBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: modalH / 2, width: modalW, height: modalH }); modalBg.alpha = 0.0; // Tamamen şeffaf yap modalBg.color = 0x181c2b; modalContainer.addChild(modalBg); var modalTitle = new Text2("Yardım", { size: 80, fill: 0xFFE066, maxWidth: modalW - 60 }); modalTitle.anchor.set(0.5, 0.5); modalTitle.x = modalW / 2; modalTitle.y = 80; modalContainer.addChild(modalTitle); var modalContent = new Text2("Gemiyi sürükle, mermilerle uzay cisimlerini vur!", { size: 50, fill: "#fff", maxWidth: modalW - 60 }); modalContent.anchor.set(0.5, 0); modalContent.x = modalW / 2; modalContent.y = 160; modalContainer.addChild(modalContent); // Kapat butonu var closeBtnW = 220; var closeBtnH = 80; var closeBtnY = modalH - 80; var closeBtnBg = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: modalW / 2, y: closeBtnY, width: closeBtnW, height: closeBtnH }); closeBtnBg.alpha = 0.85; closeBtnBg.color = 0x3a9cff; closeBtnBg.interactive = true; closeBtnBg.down = function () { return function (x, y, obj) { if (modalContainer && modalContainer.parent) modalContainer.destroy(); }; }(); modalContainer.addChild(closeBtnBg); var closeBtnText = new Text2("Kapat", { size: 60, fill: "#fff", font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'" // Modern font stack }); closeBtnText.anchor.set(0.5, 0.5); closeBtnText.x = modalW / 2; closeBtnText.y = closeBtnY; closeBtnText.interactive = true; closeBtnText.down = function (bgRef) { return function (x, y, obj) { if (bgRef && bgRef.down) bgRef.down(x, y, obj); }; }(closeBtnBg); modalContainer.addChild(closeBtnText); // Ortala ve ekrana ekle modalContainer.x = 2048 / 2 - modalW / 2; modalContainer.y = 2732 / 2 - modalH / 2; game.addChild(modalContainer); } }; }(pBtnBg); pauseMenuContainer.addChild(pBtnBg); var pBtnText = new Text2(optionsMenuButtons[i].label, { size: 80, fill: "#fff", maxWidth: pBtnW - 40 // buton kenarından taşmasın }); pBtnText.anchor.set(0.5, 0.5); pBtnText.x = pauseMenuW / 2; pBtnText.y = pBtnY; pBtnText.interactive = true; pBtnText.defaultAlpha = 1; pBtnText.down = function (btnBgRef, btnTextRef) { return function (x, y, obj) { btnTextRef.alpha = 0.65; tween(btnTextRef, { alpha: btnTextRef.defaultAlpha }, { duration: 120 }); if (btnBgRef && btnBgRef.down) btnBgRef.down(x, y, obj); }; }(pBtnBg, pBtnText); pauseMenuContainer.addChild(pBtnText); } // Ortala ve ekrana ekle pauseMenuContainer.x = 2048 / 2 - pauseMenuW / 2; pauseMenuContainer.y = 2732 / 2 - pauseMenuH / 2; game.addChild(pauseMenuContainer); gameStarted = false; } // Ava: Menü oyun durduğunda tekrar gösterilsin function showMenu() { if (!startMenuContainer.parent) { startMenuContainer.alpha = 1; startMenuContainer.scaleX = 1; startMenuContainer.scaleY = 1; game.addChild(startMenuContainer); } // Oyun yeniden başlatıldığında süreyi 3 dakikaya (180 saniye) sıfırla timeLeft = gameDuration; updateTimerDisplay(); gameStarted = false; // Boss diamond resetle if (typeof bossDiamondObj !== "undefined" && bossDiamondObj) { bossDiamondObj.destroy(); bossDiamondObj = null; } if (typeof game.bossDiamondSpawned !== "undefined") { game.bossDiamondSpawned = false; } } // Ava: Oyun durdurulduğunda dinamik pause menüsünü göster game.onPause = function () { showPauseMenu(); }; // Ava: Oyun başlatıldığında menüyü gizle (mevcut animasyonlu kod korunuyor) // (Yukarıdaki "start" butonunun down fonksiyonu zaten menüyü yok ediyor ve gameStarted=true yapıyor.) // Sağlık, skor ve zaman göstergeleri her zaman görünür (oyun başlamadan önce de) // Bu kod bloğu kaldırıldı, göstergeler her zaman görünür olacak // Her butonun kendi down fonksiyonu var, menü container'ı routing yapmaz. // Tüm ekrana tıklama ile başlatma özelliği kaldırıldı, sadece butonlar bağımsız çalışır. // Power-up türleri ve süreleri var powerUpTypes = [{ type: "rapidfire", label: "Ateş Hızı", color: 0x3a9cff, duration: 600 }, // 10 sn { type: "shield", label: "Kalkan", color: 0x7cbb37, duration: 480 }, // 8 sn { type: "scorex2", label: "2x Skor", color: 0xf7b32b, duration: 600 }, // 10 sn { type: "speedup", label: "Hız", color: 0xd729b6, duration: 480 } // 8 sn ]; var activePowerUp = null; var powerUpEndTick = 0; var powerUpIcon = null; var giftBg = null; var giftSpawnCooldown = 900; // gift nadiren spawn olsun (900 tick ~15 saniye) var lastGiftSpawnTick = -10000; // ilk başta hemen spawn olmasın function spawnGift() { if (giftBg) return; // gift zaten varsa tekrar oluşturma // 3 farklı gift: shield, health, bulletspeed var powerUpOptions = [{ type: "shield", // Kalkan label: "Kalkan", color: 0x7cbb37, assetId: "gift" // Kalkan için gift görseli }, { type: "health", // Can label: "Can", color: 0xf75b5b, assetId: "healthgift" }, { type: "bulletspeed", // Mermi hızlandırma label: "Mermi Hızı", color: 0x3a9cff, assetId: "mermispeedgift" }]; // Rastgele birini seç var pType = powerUpOptions[Math.floor(Math.random() * powerUpOptions.length)]; var assetId = pType.assetId; giftBg = LK.getAsset(assetId, { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 600, y: 2732 / 2 - 400, width: 120, height: 120 }); giftBg.alpha = 0.95; giftBg.powerUpType = pType.type; giftBg.powerUpColor = pType.color; giftBg.interactive = true; // Hareket için rastgele hızlar belirle giftBg.vx = -4 - Math.random() * 3; // sola doğru hareket giftBg.vy = (Math.random() - 0.5) * 2.5; // hafif yukarı/aşağı // Parlaklık efekti tween(giftBg, { alpha: 0.7 }, { duration: 400, yoyo: true, repeat: 9999 }); // Dokunma/çarpışma ile alınabilir ve hareketli giftBg.update = function () { // Hareket giftBg.x += giftBg.vx; giftBg.y += giftBg.vy; // Ekran dışına çıkarsa yok et if (giftBg.x < -150 || giftBg.x > 2048 + 150 || giftBg.y < -150 || giftBg.y > 2732 + 150) { giftBg.destroy(); giftBg = null; return; } // Oyuncu ile çarpışma if (playerShip && isCircleHit(giftBg, playerShip)) { // Elmas artık gift ile değil, sadece çok nadir çıkan özel bir diamond objesiyle kazanılır // Gift yakalandığında elmas verilmez, sadece power-up veya can verir if (giftBg.powerUpType === "health") { // Can hediyesi: canı artır var healAmount = 2; // Artık can hediyesi 2 can veriyor setPlayerHealth(playerHealth + healAmount); } else if (giftBg.powerUpType === "shield") { // Kalkan power-up'ı uygula activatePowerUp("shield"); } else if (giftBg.powerUpType === "bulletspeed") { // Mermi hızlandırma power-up'ı uygula activatePowerUp("bulletspeed"); } // Efekt: patlama var effect = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: giftBg.x, y: giftBg.y, width: 120, height: 120 }); effect.alpha = 0.7; game.addChild(effect); tween(effect, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { effect.destroy(); } }); giftBg.destroy(); giftBg = null; } // --- Nadiren çıkan diamond objesiyle elmas kazanma sistemi --- // Diamond objesi varsa ve oyuncu ile çarpıştıysa elmas VERİLMEZ, sadece bossDiamondObj ile verilir if (diamondObj && playerShip && isCircleHit(diamondObj, playerShip)) { // Sadece efekt göster, elmas sayacına ekleme var effect = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: diamondObj.x, y: diamondObj.y, width: 120, height: 120 }); effect.alpha = 0.7; game.addChild(effect); tween(effect, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { effect.destroy(); } }); diamondObj.destroy(); diamondObj = null; } }; game.addChild(giftBg); lastGiftSpawnTick = LK.ticks; } function activatePowerUp(type) { // Önceki power-up'ı sıfırla if (activePowerUp && powerUpIcon) { powerUpIcon.destroy(); powerUpIcon = null; } activePowerUp = type; var pType = powerUpTypes.filter(function (p) { return p.type === type; })[0]; powerUpEndTick = LK.ticks + (pType ? pType.duration : 600); // Power-up ikonunu ekle powerUpIcon = LK.getAsset('can', { anchorX: 0, anchorY: 0.5, x: 0, y: 100, width: 120, height: 120 }); powerUpIcon.alpha = 0.92; powerUpIcon.color = pType ? pType.color : 0xffffff; LK.gui.topLeft.addChild(powerUpIcon); // Üzerine metin var txt = new Text2(pType ? pType.label : "Power", { size: 38, fill: "#fff" }); txt.anchor.set(0.5, 0.5); txt.x = 60; txt.y = 60; powerUpIcon.addChild(txt); // Efekt: kısa parlama tween(powerUpIcon, { alpha: 1 }, { duration: 120, yoyo: true, repeat: 1 }); // Power-up efektini uygula if (type === "rapidfire") { shootInterval = 80; // Süper hızlı ateş } else if (type === "shield") { // Kalkan: bir sonraki hasarı engelle playerShip._shielded = true; // Görsel: geminin etrafında halka if (!playerShip._shieldCircle) { // Shield asset boyutunu playership'in etrafını tam sarmalayacak şekilde ayarla // PlayerShip'in en büyük boyutunu baz al (ellipse ise genişlik/yükseklik farklı olabilir) var maxDim = Math.max(playerShip.width, playerShip.height); var shieldMargin = 18; // Gemi ile kalkan arasında küçük bir boşluk bırak var shield = LK.getAsset('shield', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, width: maxDim + shieldMargin * 2, height: maxDim + shieldMargin * 2 }); // Shield'ı tam olarak playership'in merkezine ortala shield.x = 0; shield.y = 0; shield.alpha = 0.7; // Kalkanı tam olarak geminin merkezine hizala (anchor 0.5,0.5 ile tam ortalanır) playerShip.addChild(shield); playerShip._shieldCircle = shield; } } else if (type === "scorex2") { // Skor çarpanı game._scoreMultiplier = 2; } else if (type === "speedup") { // Geminin hızı artsın (daha hızlı sürüklenebilsin) playerShip._speedUp = true; } else if (type === "bulletspeed") { // Mermi hızı power-up: yeni mermiler daha hızlı gitsin game._bulletSpeedUp = true; // Ateş sıklığını da artır (daha hızlı ateş et) shootInterval = 120; // Normalde 250, burada daha hızlı (daha düşük değer = daha sık ateş) // Aktifken yeni mermiler hızlı olacak, Bullet sınıfı zaten bu flag'i kontrol ediyor game._multiBullet = 3; // 3 mermi birden ateşle } } function deactivatePowerUp() { if (!activePowerUp) return; // Efektleri sıfırla if (activePowerUp === "rapidfire") { shootInterval = 250; } else if (activePowerUp === "shield") { playerShip._shielded = false; if (playerShip._shieldCircle) { playerShip._shieldCircle.destroy(); playerShip._shieldCircle = null; } // Kalkan kaybolduğunda üstteki kalkan yazısı da kaybolsun if (powerUpIcon) { powerUpIcon.destroy(); powerUpIcon = null; } } else if (activePowerUp === "scorex2") { game._scoreMultiplier = 1; } else if (activePowerUp === "speedup") { playerShip._speedUp = false; } else if (activePowerUp === "bulletspeed") { game._bulletSpeedUp = false; // Artık yeni mermiler normal hızda olacak shootInterval = 250; // Ateş sıklığını normale döndür game._multiBullet = 1; // Tek mermiye dön } if (activePowerUp !== "shield" && powerUpIcon) { powerUpIcon.destroy(); powerUpIcon = null; } activePowerUp = null; powerUpEndTick = 0; } // Oyun değişkenleri var playerShip = new PlayerShip(); // Oyuncu gemisi sol alt köşeden sağa hareket edecek şekilde konumlandırılır playerShip.x = 350; playerShip.y = 2732 / 2; game.addChild(playerShip); // Oyuncu gemisinin maksimum ve başlangıç sağlığı oyuna uygun şekilde ayarlandı var playerMaxHealth = 10; // Başlangıçta 10 can var playerHealth = playerMaxHealth; // Sağlık değerini güvenli şekilde ayarlayan fonksiyon function setPlayerHealth(newHealth) { playerHealth = Math.max(0, Math.min(playerMaxHealth, newHealth)); updateCanBar(); updatePlayershipCanBar(); } var bullets = []; var spaceObjects = []; var canShoot = true; var shootInterval = 250; // ms var lastShootTick = 0; game._multiBullet = 1; // Başlangıçta tek mermi var score = 0; var difficulty = 1; var spawnInterval = 120; // ticks, kolay başlasın var lastSpawnTick = 0; shootInterval = 320; // kolay başlasın, updateDifficulty ile güncellenecek // Bölüm bitişi için toplam düşman sayacı ve kontrol değişkeni var totalEnemiesSpawned = 0; var levelFinished = false; // --- High Scores (Top 5) --- var highScores = storage.highScores && Array.isArray(storage.highScores) ? storage.highScores.slice() : []; function saveHighScores() { storage.highScores = highScores.slice(0, 5); } function addHighScore(newScore) { highScores.push(newScore); highScores.sort(function (a, b) { return b - a; }); if (highScores.length > 5) highScores.length = 5; saveHighScores(); } function getHighScores() { return highScores.slice(0, 5); } // --- PLAYERSHIP CAN BAR (HEALTH BAR) --- // Health bar dimensions // Sağlık barı genişliği ve yüksekliği yeni maksimum sağlığa uygun şekilde ayarlandı var playershipCanBarWidth = 320; // Daha kısa bar, 6 can için uygun var playershipCanBarHeight = 38; // Background bar var playershipCanBarBg = new Container(); var playershipCanBarBgRect = playershipCanBarBg.attachAsset('can', { anchorX: 0, anchorY: 0.5, x: 0, y: playershipCanBarHeight / 2, width: playershipCanBarWidth, height: playershipCanBarHeight }); playershipCanBarBgRect.alpha = 0.25; // Foreground bar var playershipCanBarFg = new Container(); var playershipCanBarFgRect = playershipCanBarFg.attachAsset('can', { anchorX: 0, anchorY: 0.5, x: 0, y: playershipCanBarHeight / 2, width: playershipCanBarWidth, height: playershipCanBarHeight }); playershipCanBarFgRect.alpha = 1; // Health bar container for positioning var playershipCanBarContainer = new Container(); playershipCanBarContainer.addChild(playershipCanBarBg); playershipCanBarContainer.addChild(playershipCanBarFg); // Position: top left, but not overlapping menu (leave 100px left and top margin) playershipCanBarContainer.x = 20; playershipCanBarContainer.y = 20; // Move to top left, just below top margin LK.gui.topLeft.addChild(playershipCanBarContainer); playershipCanBarContainer.visible = true; // Her zaman görünür // Animate health bar width and color function updatePlayershipCanBar() { // Yeni maksimum sağlığa göre oran var targetWidth = playershipCanBarWidth * Math.max(0, playerHealth) / playerMaxHealth; // Animate width using tween tween(playershipCanBarFgRect, { width: targetWidth }, { duration: 300 }); // Calculate color: green (full) to red (empty) // 0x00FF00 (green) to 0xFF0000 (red) var healthRatio = Math.max(0, Math.min(1, playerHealth / playerMaxHealth)); var r = Math.round(0xFF * (1 - healthRatio)); var g = Math.round(0xFF * healthRatio); var b = 0; var color = r << 16 | g << 8 | b; // Animate color using tween tween(playershipCanBarFgRect, { color: color }, { duration: 300 }); } updatePlayershipCanBar(); updateDifficulty(); // Oyun başında kolay zorluk ayarı uygula // --- Only one health bar is visible (playershipCanBar) --- // Animate health bar width and color function updateCanBar() { // Forward to playershipCanBar update for compatibility updatePlayershipCanBar(); } updateCanBar(); // Skor gösterimi var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); // --- Elmas sayacı --- // Elmas sayısı için global değişken var diamondCount = 0; // Elmas simgesi ve sayaç için container var diamondCounterContainer = new Container(); // Elmas simgesi (diamond asset'i ile) var diamondIcon = LK.getAsset('diamond', { anchorX: 0, anchorY: 0.5, x: 0, y: 60, width: 80, height: 80 }); diamondIcon.alpha = 0.95; diamondCounterContainer.addChild(diamondIcon); // Elmas sayısı metni var diamondTxt = new Text2('0', { size: 60, fill: "#fff" }); diamondTxt.anchor.set(0, 0.5); diamondTxt.x = diamondIcon.x + diamondIcon.width + 18; diamondTxt.y = 60; diamondCounterContainer.addChild(diamondTxt); // Elmas sayacını güncelleyen fonksiyon function updateDiamondCounter() { diamondTxt.setText(diamondCount + ""); } updateDiamondCounter(); // Skor ve elmas sayaçlarını yan yana göstermek için ortak bir container oluştur var scoreDiamondContainer = new Container(); scoreDiamondContainer.addChild(scoreTxt); // Elmas sayacını skorun sağına hizala diamondCounterContainer.x = scoreTxt.width / 2 + 32; // skorun sağında 32px boşluk diamondCounterContainer.y = 0; scoreDiamondContainer.addChild(diamondCounterContainer); // Ortak container'ı GUI'de üstte ortala scoreDiamondContainer.x = 0; scoreDiamondContainer.y = 0; LK.gui.top.addChild(scoreDiamondContainer); scoreTxt.visible = true; // Her zaman görünür // Süre göstergesi (3 dakika = 180 saniye) var gameDuration = 180; // saniye var timeLeft = gameDuration; var timerTxt = new Text2('03:00', { size: 100, fill: "#fff" }); timerTxt.anchor.set(1, 0); // Anchor right edge LK.gui.topRight.addChild(timerTxt); // Add to right side of GUI timerTxt.visible = true; // Her zaman görünür // Timer'ı güncelleyen fonksiyon function updateTimerDisplay() { var min = Math.floor(timeLeft / 60); var sec = Math.floor(timeLeft % 60); var minStr = min < 10 ? "0" + min : "" + min; var secStr = sec < 10 ? "0" + sec : "" + sec; timerTxt.setText(minStr + ":" + secStr); } updateTimerDisplay(); // Her saniye zaman azaltıcı timer var timerInterval = LK.setInterval(function () { if (!gameStarted) return; if (levelFinished) return; if (timeLeft > 0) { timeLeft -= 1; if (timeLeft < 0) timeLeft = 0; updateTimerDisplay(); // Zaman bittiğinde oyunu otomatik olarak yeniden başlat if (timeLeft === 0) { LK.restartGame(); } } }, 1000); // Animate health bar width and color updateCanBar(); // Dokunma/sürükleme ile gemi hareketi var dragging = false; function handleMove(x, y, obj) { if (!gameStarted) return; if (dragging) { // Portal büyüme animasyonu sırasında oyuncu hareket etmesin, ancak büyüme bittiyse tekrar izin ver var portalGrowing = false; if (game.portal && !game.portal.isShrinking) { // Portal büyüme animasyonu devam ediyor mu? // 1.2'den 3.0'a büyüme: scaleX < 3.0 ise büyüme devam ediyor if (typeof game.portal._growTweenStarted !== "undefined" && game.portal._growTweenStarted && game.portal.scaleX < 3.0 - 0.01) { portalGrowing = true; } } if (portalGrowing) { return; } // Sınırları aşmasın - boss sonrası üst/alt bar varsa daraltılmış alanda hareket var minX = playerShip.width / 2 + 40; var maxX = 2048 - playerShip.width / 2 - 40; var minY, maxY; if (game._screenNarrowed && typeof game._playAreaTop !== "undefined" && typeof game._playAreaBottom !== "undefined") { minY = game._playAreaTop + playerShip.height / 2 + 20; maxY = game._playAreaBottom - playerShip.height / 2 - 20; } else { minY = playerShip.height / 2 + 40; maxY = 2732 - playerShip.height / 2 - 40; } // Sadece sürükleme sırasında, gemi mouse/touch ile birlikte hareket eder if (activePowerUp === "speedup") { // Hız power-up'ı: gemi daha hızlı hareket etsin (pozisyona yaklaşma) playerShip.x += (Math.max(minX, Math.min(maxX, x)) - playerShip.x) * 0.45; playerShip.y += (Math.max(minY, Math.min(maxY, y)) - playerShip.y) * 0.45; } else { playerShip.x = Math.max(minX, Math.min(maxX, x)); playerShip.y = Math.max(minY, Math.min(maxY, y)); } } } game.move = handleMove; game.down = function (x, y, obj) { // Sadece geminin üstüne tıklanırsa sürükleme başlasın if (!gameStarted) return; var dx = x - playerShip.x; var dy = y - playerShip.y; var r = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70); // Portal büyüme animasyonu devam ediyorsa sürükleme başlatılamasın var portalGrowing = false; if (game.portal && !game.portal.isShrinking) { if (!game.portal._growTweenStarted || game.portal.scaleX < 1.8 - 0.01) { portalGrowing = true; } } if (portalGrowing) { dragging = false; return; } if (dx * dx + dy * dy <= r * r) { dragging = true; handleMove(x, y, obj); } else { dragging = false; } }; game.up = function (x, y, obj) { if (!gameStarted) return; dragging = false; }; // Otomatik ateş (her shootInterval ms'de bir) function tryShoot() { if (!canShoot) return; var multi = typeof game._multiBullet !== "undefined" ? game._multiBullet : 1; var spread = 38; // mermiler arası dikey mesafe for (var i = 0; i < multi; i++) { var bullet = new Bullet(); bullet.x = playerShip.x + playerShip.width / 2 + 10; // Ortadaki mermi tam ortada, diğerleri yukarı ve aşağıya kaydırılır bullet.y = playerShip.y + (i - (multi - 1) / 2) * spread; bullets.push(bullet); game.addChild(bullet); } canShoot = false; LK.setTimeout(function () { canShoot = true; }, shootInterval); } // Uzay cismi oluştur function spawnSpaceObject() { // 0: uzayNesnesi2 (enemy), 1: spaceObject (asteroid), 2: meteorstone (yeni düşman) // Düşman gemilerinin sıklığını artırmak için oranı yükselttik var rand = Math.random(); var obj; // enemyship2 sadece zorluk 4 ve üstünde görünsün if (rand < 0.6 && difficulty >= 4) { // Only allow one enemyship2 on screen at a time var hasEnemyship2 = false; for (var i = 0; i < spaceObjects.length; i++) { var so = spaceObjects[i]; if (so.attachAsset && so.attachAsset('enemyship2', { anchorX: 0.5, anchorY: 0.5 })) { hasEnemyship2 = true; break; } } if (hasEnemyship2) { // Do not spawn another enemyship2 return; } // enemyship2 (yeni düşman tipi) obj = new Container(); obj.health = 20; // enemyship2 canı 20 olarak başlatıldı var width = 300; var height = 300; var objAsset = obj.attachAsset('enemyship2', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; objAsset.color = 0xff4444; obj.radius = width / 2; obj.x = 2048 + width; obj.y = 200 + Math.random() * (2732 - 400); // Düşman hızı: kolayda yavaş, zorda hızlı var baseSpeed = 4 + (difficulty - 4) * 0.8; var speed = baseSpeed + Math.random() * (2.0 + difficulty * 0.3); obj.vx = -speed; obj.vy = (Math.random() - 0.5) * (3.5 + difficulty * 0.3); // --- EN AZ 10 SANİYE EKRANDA KALMA --- // enemyship2 ekranda kalma süresi (tick cinsinden) obj._minScreenTicks = 600; // 10 saniye (60fps) // enemyship2'nin ekranda kalmaya başladığı tick obj._spawnTick = LK.ticks; // enemyship2 yok edilebilir mi? (başta false, 10sn sonra true) obj._canBeDestroyed = false; // --- RANDOM SALDIRI MEKANİĞİ --- // Rastgele saldırı için bir sonraki saldırı tick'i obj._nextRandomAttackTick = LK.ticks + 60 + Math.floor(Math.random() * 120); // 1-3 sn arası ilk saldırı // Enemy bullet fire timer obj.enemyBulletCooldown = 7 + Math.floor(Math.random() * 7); // DAHA DA SIK ateş (daha seri) obj.lastEnemyBulletTick = LK.ticks; // --- LAZER IŞINI: enemyship2 özel saldırısı --- // Lazer ışını için state ve timerlar obj.laserCooldown = 240 + Math.floor(Math.random() * 120); // 4-6 saniyede bir obj.lastLaserTick = LK.ticks; obj.laserActive = false; obj.laserDuration = 60; // lazer açık kalma süresi (1 saniye) obj.laserBeam = null; // Lazer ateşleme etkin: enemyship2 için lazer saldırısı aktif // --- YAPAY ZEKA: Oyuncuya yaklaşma ve akıllı ateş etme --- obj.update = function () { // Akıllı hareket: oyuncuya doğru yavaşça yönel if (playerShip && typeof playerShip.x !== "undefined" && typeof playerShip.y !== "undefined") { var dx = playerShip.x - obj.x; var dy = playerShip.y - obj.y; var dist = Math.sqrt(dx * dx + dy * dy); // X ekseninde oyuncuya yaklaşmak için vx'yi ayarla var targetVx = -Math.max(3, Math.min(12, Math.abs(dx) / 30)); if (obj.x > playerShip.x) { obj.vx += (targetVx - obj.vx) * 0.10; } // Y ekseninde oyuncuya yaklaşmak için vy'yi ayarla var targetVy = 0; if (dist > 1) { targetVy = dy / Math.max(60, Math.abs(dx)); if (targetVy > 6) targetVy = 6; if (targetVy < -6) targetVy = -6; } obj.vy += (targetVy - obj.vy) * 0.15; } obj.x += obj.vx; obj.y += obj.vy; // --- EKRANA GİRİNCE ATEŞ ETME BAŞLASIN --- // Ekrana ilk kez girdiği anı tespit et if (typeof obj._hasStartedFiring === "undefined") obj._hasStartedFiring = false; if (!obj._hasStartedFiring && obj.x <= 2048) { obj._hasStartedFiring = true; // İlk ateş için timerları hemen başlat obj.lastEnemyBulletTick = LK.ticks; if (typeof obj._nextRandomAttackTick !== "undefined") { obj._nextRandomAttackTick = LK.ticks + 10 + Math.floor(Math.random() * 30); // Hemen random saldırı başlat } if (typeof obj.laserStartTick !== "undefined") { obj.laserStartTick = LK.ticks; } } // --- EN AZ 10 SANİYE EKRANDA KALMA KONTROLÜ --- if (!obj._canBeDestroyed && LK.ticks - obj._spawnTick >= obj._minScreenTicks) { obj._canBeDestroyed = true; } // --- RANDOM SALDIRI MEKANİĞİ --- // 10 saniye dolduysa random saldırı yapabilir if (LK.ticks - obj._spawnTick >= obj._minScreenTicks && LK.ticks >= obj._nextRandomAttackTick) { // Saldırı türünü rastgele seç: 0=normal mermi, 1=lazer, 2=çift mermi, 3=ani hızlanma var attackType = Math.floor(Math.random() * 4); if (attackType === 0) { // Normal mermi ateşi (hedefli) var eb = new EnemyBullet(); eb.x = obj.x - 60; eb.y = obj.y; if (!game.enemyBullets) game.enemyBullets = []; game.enemyBullets.push(eb); game.addChild(eb); } else if (attackType === 1 && !obj.laserActive) { // Lazer saldırısı başlat (lazer zaten aktif değilse) obj.laserActive = true; obj.laserStartTick = LK.ticks; var laserLength = obj.x - 0; var laserWidth = 38 + Math.random() * 18; var laserY = obj.y; obj.laserBeam = LK.getAsset('lazer', { anchorX: 1.0, anchorY: 0.5, x: obj.x - width / 2 - 10, y: laserY, width: laserLength, height: laserWidth }); obj.laserBeam.alpha = 0.38 + Math.random() * 0.18; obj.laserBeam.laserOwner = obj; obj.laserBeam._baseY = laserY; obj.laserBeam._baseWidth = laserWidth; obj.laserBeam.update = function () { if (!obj.laserActive) return; obj.laserBeam.y = obj.y; obj.laserBeam.width = obj.x - 0; obj.laserBeam.height = obj.laserBeam._baseWidth + Math.sin(LK.ticks / 2) * 8; obj.laserBeam.alpha = 0.38 + Math.abs(Math.sin(LK.ticks / 8)) * 0.22; }; game.addChild(obj.laserBeam); } else if (attackType === 2) { // Çift mermi ateşi (yukarı ve aşağı) for (var i = -1; i <= 1; i += 2) { var eb2 = new EnemyBullet(); eb2.x = obj.x - 60; eb2.y = obj.y + i * 60; if (!game.enemyBullets) game.enemyBullets = []; game.enemyBullets.push(eb2); game.addChild(eb2); } } else if (attackType === 3) { // Ani hızlanma (kısa süre için vx artır) obj.vx -= 6 + Math.random() * 4; } // Bir sonraki random saldırı için tick ayarla (her seferinde 1-3 sn arası) obj._nextRandomAttackTick = LK.ticks + 60 + Math.floor(Math.random() * 120); } // --- LAZER IŞINI AKTİVASYONU --- // Lazer aktif değilse ve cooldown dolduysa lazeri başlat if (!obj.laserActive && LK.ticks - obj.lastLaserTick > obj.laserCooldown) { obj.laserActive = true; obj.laserStartTick = LK.ticks; // Lazer ışını görseli: lazer image asset'i ile (kırmızı, şeffaf) var laserLength = obj.x - 0; // Ekranın soluna kadar var laserWidth = 38 + Math.random() * 18; // 38-56px arası var laserY = obj.y; obj.laserBeam = LK.getAsset('lazer', { anchorX: 1.0, anchorY: 0.5, x: obj.x - width / 2 - 10, y: laserY, width: laserLength, height: laserWidth }); obj.laserBeam.alpha = 0.38 + Math.random() * 0.18; obj.laserBeam.laserOwner = obj; // Hafif titreme efekti için orijinal y ve width kaydet obj.laserBeam._baseY = laserY; obj.laserBeam._baseWidth = laserWidth; // Lazer update fonksiyonu: objenin y'sini takip etsin, titreme efekti obj.laserBeam.update = function () { if (!obj.laserActive) return; // Lazerin y'si enemyship2'nin y'sini takip etsin obj.laserBeam.y = obj.y; // Lazerin uzunluğu obj.x'den ekrandaki en sol noktaya kadar obj.laserBeam.width = obj.x - 0; // Hafif titreme efekti obj.laserBeam.height = obj.laserBeam._baseWidth + Math.sin(LK.ticks / 2) * 8; obj.laserBeam.alpha = 0.38 + Math.abs(Math.sin(LK.ticks / 8)) * 0.22; }; game.addChild(obj.laserBeam); } // Lazer aktifse, süresi dolduysa kapat if (obj.laserActive) { if (LK.ticks - obj.laserStartTick > obj.laserDuration) { obj.laserActive = false; obj.lastLaserTick = LK.ticks; obj.laserCooldown = 240 + Math.floor(Math.random() * 120); if (obj.laserBeam && obj.laserBeam.parent) { obj.laserBeam.destroy(); } obj.laserBeam = null; } else if (obj.laserBeam && obj.laserBeam.update) { obj.laserBeam.update(); // Lazer ışını ile oyuncu çarpışma kontrolü (dikdörtgen-çember) // Lazerin dikdörtgeni: (x1, y1, x2, y2) var lx1 = obj.laserBeam.x - obj.laserBeam.width; var lx2 = obj.laserBeam.x; var ly1 = obj.laserBeam.y - obj.laserBeam.height / 2; var ly2 = obj.laserBeam.y + obj.laserBeam.height / 2; // Oyuncu çemberi if (playerShip) { var px = playerShip.x; var py = playerShip.y; var pr = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70); // Çember-dikdörtgen çarpışma var closestX = Math.max(lx1, Math.min(px, lx2)); var closestY = Math.max(ly1, Math.min(py, ly2)); var dx = px - closestX; var dy = py - closestY; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < pr - 8) { // Sadece ilk çarpışmada hasar uygula (her frame değil) if (!obj.laserBeam._playerHit) { obj.laserBeam._playerHit = true; // Patlama efekti var explosion = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width || 140, height: playerShip.height || 100 }); game.addChild(explosion); tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { explosion.destroy(); } }); // Kalkan power-up aktifse ilk hasarı engelle if (activePowerUp === "shield" && playerShip._shielded) { playerShip._shielded = false; if (playerShip._shieldCircle) { tween(playerShip._shieldCircle, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { playerShip._shieldCircle.destroy(); playerShip._shieldCircle = null; } }); } var shieldHit = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width * 1.7, height: playerShip.height * 1.7 }); shieldHit.alpha = 0.5; shieldHit.color = 0x7cbb37; game.addChild(shieldHit); tween(shieldHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { shieldHit.destroy(); } }); // Hasarı engelle, can azalmasın } else { setPlayerHealth(playerHealth - 4); // Lazer ışını hasarı } if (playerHealth <= 0) { LK.showGameOver(); return; } } } else { obj.laserBeam._playerHit = false; } } } } // Ateş etme (her cooldown süresi dolduğunda) if (LK.ticks - obj.lastEnemyBulletTick > obj.enemyBulletCooldown) { // Oyuncuya odaklı ateş: eğer oyuncu yatayda önünde ve menzildeyse ateş et, yoksa rastgele daha az ateş etsin var shouldFire = false; if (playerShip && obj.x > playerShip.x) { // Düşman oyuncunun sağında olmalı var dy = Math.abs(obj.y - playerShip.y); // Y ekseninde yakınlık arttıkça ateş olasılığı artsın if (dy < 80) { shouldFire = true; // Çok yakınsa kesin ateş et } else if (dy < 180 && Math.random() < 0.5) { shouldFire = true; // Orta mesafede %50 olasılıkla ateş et } else if (dy < 300 && Math.random() < 0.15) { shouldFire = true; // Uzakta ise nadiren ateş et } } else if (Math.random() < 0.03) { // Ekranda oyuncu yoksa veya çok uzaktaysa çok nadiren ateş etsin shouldFire = true; } if (shouldFire) { var eb = new EnemyBullet(); eb.x = obj.x - 60; eb.y = obj.y; if (!game.enemyBullets) game.enemyBullets = []; game.enemyBullets.push(eb); game.addChild(eb); obj.lastEnemyBulletTick = LK.ticks; // Oyuncuya yakınken daha kısa cooldown, uzaktayken daha uzun if (playerShip && Math.abs(obj.y - playerShip.y) < 80) { obj.enemyBulletCooldown = 14 + Math.floor(Math.random() * 8); // Çok yakınsa çok sık ateş } else if (playerShip && Math.abs(obj.y - playerShip.y) < 180) { obj.enemyBulletCooldown = 22 + Math.floor(Math.random() * 12); // Orta mesafe } else { obj.enemyBulletCooldown = 38 + Math.floor(Math.random() * 22); // Uzakta daha seyrek ateş } } } }; } else if (rand < 0.6) { // uzayNesnesi2 (enemy ship) - eski düşman, sadece zorluk 4'ten önce obj = new Container(); var width = 100; var height = 100; var objAsset = obj.attachAsset('uzayNesnesi2', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; objAsset.color = 0xff4444; obj.radius = width / 2; obj.x = 2048 + width; obj.y = 200 + Math.random() * (2732 - 400); // Düşman hızı: kolayda yavaş, zorda hızlı // 1. zorlukta ~3, 10. zorlukta ~9 var baseSpeed = 3 + (difficulty - 1) * 0.7; var speed = baseSpeed + Math.random() * (1.5 + difficulty * 0.2); obj.vx = -speed; obj.vy = (Math.random() - 0.5) * (2.5 + difficulty * 0.2); // Enemy bullet fire timer obj.enemyBulletCooldown = 10 + Math.floor(Math.random() * 10); // DAHA DA SIK ateş (daha seri) obj.lastEnemyBulletTick = LK.ticks; // --- YAPAY ZEKA: Oyuncuya yaklaşma ve akıllı ateş etme --- obj.update = function () { // Akıllı hareket: oyuncuya doğru yavaşça yönel if (playerShip && typeof playerShip.x !== "undefined" && typeof playerShip.y !== "undefined") { // Yalnızca ekranda ise takip et var dx = playerShip.x - obj.x; var dy = playerShip.y - obj.y; var dist = Math.sqrt(dx * dx + dy * dy); // X ekseninde oyuncuya yaklaşmak için vx'yi ayarla (mantıklı takip) var targetVx = -Math.max(2, Math.min(10, Math.abs(dx) / 40)); if (obj.x > playerShip.x) { obj.vx += (targetVx - obj.vx) * 0.08; } // Y ekseninde oyuncuya yaklaşmak için vy'yi ayarla (smooth takip) var targetVy = 0; if (dist > 1) { targetVy = dy / Math.max(80, Math.abs(dx)); // X uzaklığı arttıkça daha az dikey hareket // Sınırla, çok hızlı olmasın if (targetVy > 4) targetVy = 4; if (targetVy < -4) targetVy = -4; } // Yavaşça vy'ye yaklaş obj.vy += (targetVy - obj.vy) * 0.12; } obj.x += obj.vx; obj.y += obj.vy; // --- EKRANA GİRİNCE ATEŞ ETME BAŞLASIN --- // Ekrana ilk kez girdiği anı tespit et if (typeof obj._hasStartedFiring === "undefined") obj._hasStartedFiring = false; if (!obj._hasStartedFiring && obj.x <= 2048) { obj._hasStartedFiring = true; // İlk ateş için timerı hemen başlat obj.lastEnemyBulletTick = LK.ticks; } // Ateş etme (her cooldown süresi dolduğunda) if (LK.ticks - obj.lastEnemyBulletTick > obj.enemyBulletCooldown) { // Oyuncuya odaklı ateş: eğer oyuncu yatayda önünde ve menzildeyse ateş et, yoksa rastgele daha az ateş etsin var shouldFire = false; if (playerShip && obj.x > playerShip.x) { var dy = Math.abs(obj.y - playerShip.y); if (dy < 60) { shouldFire = true; // Çok yakınsa kesin ateş et } else if (dy < 140 && Math.random() < 0.5) { shouldFire = true; // Orta mesafe %50 olasılıkla ateş et } else if (dy < 220 && Math.random() < 0.12) { shouldFire = true; // Uzakta ise nadiren ateş et } } else if (Math.random() < 0.02) { // Ekranda oyuncu yoksa veya çok uzaktaysa çok nadiren ateş etsin shouldFire = true; } if (shouldFire) { var eb = new EnemyBullet(); eb.x = obj.x - 60; eb.y = obj.y; if (!game.enemyBullets) game.enemyBullets = []; game.enemyBullets.push(eb); game.addChild(eb); obj.lastEnemyBulletTick = LK.ticks; // Oyuncuya yakınken daha kısa cooldown, uzaktayken daha uzun if (playerShip && Math.abs(obj.y - playerShip.y) < 60) { obj.enemyBulletCooldown = 18 + Math.floor(Math.random() * 8); // Çok yakınsa çok sık ateş } else if (playerShip && Math.abs(obj.y - playerShip.y) < 140) { obj.enemyBulletCooldown = 28 + Math.floor(Math.random() * 10); // Orta mesafe } else { obj.enemyBulletCooldown = 54 + Math.floor(Math.random() * 24); // Uzakta daha seyrek ateş } } } }; } else if (rand < 0.3) { // spaceObject (asteroid) obj = new Container(); var width = 120 + Math.random() * 60; var height = 120 + Math.random() * 60; var objAsset = obj.attachAsset('spaceObject', { anchorX: 0.5, anchorY: 0.5 }); objAsset.width = width; objAsset.height = height; objAsset.color = 0x888888; obj.radius = width / 2; obj.x = 2048 + width; obj.y = 200 + Math.random() * (2732 - 400); // Asteroid hızı: kolayda yavaş, zorda hızlı // 1. zorlukta ~2.5, 10. zorlukta ~8 var baseSpeed = 2.5 + (difficulty - 1) * 0.6; var speed = baseSpeed + Math.random() * (1.5 + difficulty * 0.2); obj.vx = -speed; obj.vy = (Math.random() - 0.5) * (2 + difficulty * 0.2); obj.update = function () { obj.x += obj.vx; obj.y += obj.vy; }; } else { // meteorstone (yeni düşman) // MeteorStone: kolayda yavaş, zorda hızlı obj = new MeteorStone(); if (obj && obj.vx !== undefined) { // 1. zorlukta ~-3, 10. zorlukta ~-8 var meteorBaseSpeed = 3 + (difficulty - 1) * 0.6; obj.vx = -meteorBaseSpeed - Math.random() * (1.5 + difficulty * 0.2); obj.vy = (Math.random() - 0.5) * (2.5 + difficulty * 0.2); } } spaceObjects.push(obj); game.addChild(obj); // Düşman sayısını artır ve 10'a ulaştıysa win kontrolü totalEnemiesSpawned++; // (Kazanan kontrolü kaldırıldı) } // Çarpışma kontrolü (daire-çarpışma) function isCircleHit(a, b) { var dx = a.x - b.x; var dy = a.y - b.y; var dist = Math.sqrt(dx * dx + dy * dy); var r1 = a.radius || (a.width ? a.width / 2 : 0); var r2 = b.radius || (b.width ? b.width / 2 : 0); return dist < r1 + r2 - 10; } // Zorluk arttırma ve oyun hızını kademeli olarak artır function updateDifficulty() { // Zorluk: 1-10 arası, her 10 puanda bir artar, maksimum 10 var newDifficulty = 1 + Math.floor(score / 10); if (newDifficulty > 10) newDifficulty = 10; if (newDifficulty > difficulty) { difficulty = newDifficulty; } // spawnInterval: Kolayda yavaş (120), zorda hızlı (30) // 1. zorlukta 120, 10. zorlukta 30 spawnInterval = Math.round(120 - (difficulty - 1) * 10); if (spawnInterval < 30) spawnInterval = 30; // Mermi hızını ve ateş sıklığını zorlukla birlikte artır // Kolayda yavaş, zorda hızlı // shootInterval: 1. zorlukta 320, 10. zorlukta 120 shootInterval = Math.round(320 - (difficulty - 1) * 22); if (shootInterval < 90) shootInterval = 90; // Düşman mermisi hızı ve spawn oranı da zorlukla birlikte artacak şekilde ayarlanabilir // (EnemyShip ve Asteroid spawn fonksiyonlarında da difficulty kullanılıyor) } // Oyun döngüsü game.update = function () { // (Geri alındı: ekran sağa doğru ilerlemesin, scrollX ve scrollSpeed kaldırıldı) // Galaksi arka planı kaldırıldı // Yıldızlar: parallax ve hafif döndürme if (typeof starBgContainer !== "undefined" && stars && stars.length) { for (var si = 0; si < stars.length; si++) { var s = stars[si]; s.x -= s._vx; s.rotation += s._rotSpeed; // Ekrandan soldan çıkarsa sağa wrap et if (s.x < -10) { s.x = 2048 + 10; s.y = Math.random() * 2732; } } } if (!gameStarted) return; // Playership sağlık barı 0 olduğunda oyun bitsin, aksi takdirde bitmesin if (playerHealth <= 0) { updateCanBar(); updatePlayershipCanBar(); // --- High Score Save --- addHighScore(score); // Boss diamond resetle if (typeof bossDiamondObj !== "undefined" && bossDiamondObj) { bossDiamondObj.destroy(); bossDiamondObj = null; } if (typeof game.bossDiamondSpawned !== "undefined") { game.bossDiamondSpawned = false; } LK.showGameOver(); return; } // Süreyi azalt (her frame ~1/60 saniye) // Artık sadece timerInterval ile zaman azalacak, burada azaltma yapılmıyor // 10 düşman spawn olduysa ve can > 0 ve süre > 0 ise win // (Kazanan kontrolü kaldırıldı) // Planets removed // Otomatik ateş // Portal büyüme veya küçülme animasyonu sırasında mermi atılmasın var portalBlockingShoot = false; if (game.portal && !game.portal.isShrinking && typeof game.portal.lastWasIntersecting !== "undefined" && game.portal.lastWasIntersecting) { portalBlockingShoot = true; } if (!portalBlockingShoot && LK.ticks - lastShootTick > Math.floor(shootInterval / 16)) { tryShoot(); lastShootTick = LK.ticks; } // Uzay cismi oluşturma if (!levelFinished && LK.ticks - lastSpawnTick > spawnInterval) { spawnSpaceObject(); lastSpawnTick = LK.ticks; } // Mermileri güncelle if (!(game.portal && !game.portal.isShrinking && game.portal.scaleX < (typeof maxScale !== "undefined" ? maxScale : 999))) { // Portal büyüme animasyonu sırasında mermiler yok edilir for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); // Ekran dışıysa sil if (b.x > 2048 + 50) { b.destroy(); bullets.splice(i, 1); } } } else { // Portal büyüme animasyonu sırasında tüm mermileri yok et for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; if (b && b.parent) { tween(b, { alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 200, onFinish: function (bb) { return function () { if (bb && bb.parent) bb.destroy(); }; }(b) }); } } bullets = []; } // Uzay cisimlerini güncelle for (var j = spaceObjects.length - 1; j >= 0; j--) { var obj = spaceObjects[j]; obj.update(); // Ekran dışıysa sil if (obj.x < -200 || obj.y < -200 || obj.y > 2732 + 200) { obj.destroy(); spaceObjects.splice(j, 1); continue; } // Gemiye çarptı mı? if (isCircleHit(obj, playerShip)) { // Eğer kalkan aktifse, hiçbir şey olmasın, düşman da yok olmasın if (activePowerUp === "shield" && playerShip._shielded) { // Kalkan varken düşman çarpışması tamamen etkisiz, hiçbir efekt, hasar veya yok etme işlemi yapılmaz continue; } // Patlama efekti (patlamaeffekt görseli ile) oyuncu gemisinin üstünde göster var explosion = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width || 140, height: playerShip.height || 100 }); game.addChild(explosion); tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { explosion.destroy(); } }); // Farklı düşman türlerine göre hasar uygula var damage = 1; if (obj instanceof MeteorStone) { damage = 3; } else if (obj.attachAsset && obj.attachAsset('uzayNesnesi2', { anchorX: 0.5, anchorY: 0.5 })) { // EnemyShip ise 2 birim (uzayNesnesi2) damage = 2; } else if (obj.attachAsset && obj.attachAsset('spaceObject', { anchorX: 0.5, anchorY: 0.5 })) { // SpaceObject asteroid ise 1 birim damage = 1; } setPlayerHealth(playerHealth - damage); if (playerHealth <= 0) { LK.showGameOver(); return; } obj.destroy(); spaceObjects.splice(j, 1); continue; } // Mermiyle çarpışma var _loop = function _loop() { b = bullets[k]; if (isCircleHit(obj, b)) { // Patlama efekti (patlamaeffekt görseli ile) explosion = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: obj.x, y: obj.y, width: obj.width || 100, height: obj.height || 100 }); game.addChild(explosion); tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { explosion.destroy(); } }); // enemyship2 ise (büyük kırmızı gemi), 2 mermi isabet edince yok olsun if (obj.attachAsset && obj.attachAsset('enemyship2', { anchorX: 0.5, anchorY: 0.5 })) { // Skor: enemyship2 için 5 puan verelim (isteğe bağlı, 3 de olabilir) // --- Ava: 2 mermi isabet edince yok olma sistemi --- if (typeof obj._hitCount === "undefined") obj._hitCount = 0; obj._hitCount++; b.destroy(); bullets.splice(k, 1); if (obj._hitCount >= 2) { var scoreToAdd = 5; obj.destroy(); spaceObjects.splice(j, 1); var multiplier = game._scoreMultiplier && game._scoreMultiplier > 1 ? game._scoreMultiplier : 1; score += scoreToAdd * multiplier; scoreTxt.setText(score); updateDifficulty(); // Bölüm sonu: 10 düşman öldürüldüyse bitir if (!levelFinished) { if (typeof game.enemiesKilled === "undefined") game.enemiesKilled = 0; game.enemiesKilled++; if (game.enemiesKilled >= 50) { levelFinished = true; // Bölüm sonu canavarı görselini göster if (typeof game.bossImageShown === "undefined" || !game.bossImageShown) { var _flashBoss = function flashBoss() { if (!game.bossImg) return; tween(game.bossImg, { alpha: 1 }, { duration: 120, onFinish: function onFinish() { tween(game.bossImg, { alpha: 0 }, { duration: 120, onFinish: function onFinish() { flashCount++; if (flashCount < 3) { _flashBoss(); } else { // Sonunda kalıcı olarak görünür olsun tween(game.bossImg, { alpha: 1 }, { duration: 120 }); } } }); } }); }; // Sağda, birden yanıp sönerek beliren ve aşağı yukarı hareket eden boss bossImg = LK.getAsset('bolumsonucanavar', { anchorX: 0.5, anchorY: 0.5, // Ekranın sağında, ortalanmış şekilde göster x: 2048 - 200, y: 2732 / 2, width: 400, height: 400 }); bossImg.alpha = 0; game.addChild(bossImg); game.bossImageShown = true; game.bossImg = bossImg; game.bossAppearTick = LK.ticks; // Yanıp sönme animasyonu (3 kez) flashCount = 0; _flashBoss(); // Boss'un aşağı yukarı hareketi için tick kaydı game.bossBaseY = bossImg.y; // --- SADECE BÖLÜM SONU CANAVARI KALSIN --- // Tüm uzay cisimlerini sil for (var jj = spaceObjects.length - 1; jj >= 0; jj--) { if (spaceObjects[jj]) { spaceObjects[jj].destroy(); } } spaceObjects = []; // Tüm mermileri sil for (var ii = bullets.length - 1; ii >= 0; ii--) { if (bullets[ii]) { bullets[ii].destroy(); } } bullets = []; // Tüm düşman mermilerini sil if (game.enemyBullets) { for (var eb = game.enemyBullets.length - 1; eb >= 0; eb--) { if (game.enemyBullets[eb]) { game.enemyBullets[eb].destroy(); } } game.enemyBullets = []; } // Gift varsa sil if (giftBg) { giftBg.destroy(); giftBg = null; } } // Oyun bitmesin, win popup gösterme return { v: void 0 }; } } return 0; // break } } else { obj.destroy(); spaceObjects.splice(j, 1); b.destroy(); bullets.splice(k, 1); // Skor: meteorstone=2, spaceObject=1, enemy ship=3 var scoreToAdd = 1; // MeteorStone ise 2 puan if (obj instanceof MeteorStone) { scoreToAdd = 2; } // EnemyShip ise 3 puan else if (obj.attachAsset && obj.attachAsset('uzayNesnesi2', { anchorX: 0.5, anchorY: 0.5 })) { scoreToAdd = 3; } // SpaceObject asteroid ise 1 puan (default) else if (obj.attachAsset && obj.attachAsset('spaceObject', { anchorX: 0.5, anchorY: 0.5 })) { scoreToAdd = 1; } } // Power-up skor çarpanı uygula var multiplier = game._scoreMultiplier && game._scoreMultiplier > 1 ? game._scoreMultiplier : 1; score += scoreToAdd * multiplier; scoreTxt.setText(score); updateDifficulty(); // Bölüm sonu: 10 düşman öldürüldüyse bitir if (!levelFinished) { if (typeof game.enemiesKilled === "undefined") game.enemiesKilled = 0; game.enemiesKilled++; if (game.enemiesKilled >= 50) { levelFinished = true; // Bölüm sonu canavarı görselini göster if (typeof game.bossImageShown === "undefined" || !game.bossImageShown) { var _flashBoss = function flashBoss() { if (!game.bossImg) return; tween(game.bossImg, { alpha: 1 }, { duration: 120, onFinish: function onFinish() { tween(game.bossImg, { alpha: 0 }, { duration: 120, onFinish: function onFinish() { flashCount++; if (flashCount < 3) { _flashBoss(); } else { // Sonunda kalıcı olarak görünür olsun tween(game.bossImg, { alpha: 1 }, { duration: 120 }); } } }); } }); }; // Sağda, birden yanıp sönerek beliren ve aşağı yukarı hareket eden boss bossImg = LK.getAsset('bolumsonucanavar', { anchorX: 0.5, anchorY: 0.5, // Ekranın sağında, ortalanmış şekilde göster x: 2048 - 200, y: 2732 / 2, width: 400, height: 400 }); bossImg.alpha = 0; game.addChild(bossImg); game.bossImageShown = true; game.bossImg = bossImg; game.bossAppearTick = LK.ticks; // Yanıp sönme animasyonu (3 kez) flashCount = 0; _flashBoss(); // Boss'un aşağı yukarı hareketi için tick kaydı game.bossBaseY = bossImg.y; // --- SADECE BÖLÜM SONU CANAVARI KALSIN --- // Tüm uzay cisimlerini sil for (var jj = spaceObjects.length - 1; jj >= 0; jj--) { if (spaceObjects[jj]) { spaceObjects[jj].destroy(); } } spaceObjects = []; // Tüm mermileri sil for (var ii = bullets.length - 1; ii >= 0; ii--) { if (bullets[ii]) { bullets[ii].destroy(); } } bullets = []; // Tüm düşman mermilerini sil if (game.enemyBullets) { for (var eb = game.enemyBullets.length - 1; eb >= 0; eb--) { if (game.enemyBullets[eb]) { game.enemyBullets[eb].destroy(); } } game.enemyBullets = []; } // Gift varsa sil if (giftBg) { giftBg.destroy(); giftBg = null; } } // Oyun bitmesin, win popup gösterme return { v: void 0 }; } } return 0; // break } }, b, explosion, scoreToAdd, bossImg, flashCount, _ret; for (var k = bullets.length - 1; k >= 0; k--) { _ret = _loop(); if (_ret === 0) break; if (_ret) return _ret.v; } } // Düşman mermileri güncelle ve çarpışma kontrolü if (game.enemyBullets) { for (var eb = game.enemyBullets.length - 1; eb >= 0; eb--) { var enemyBullet = game.enemyBullets[eb]; enemyBullet.update(); // Ekran dışıysa sil if (enemyBullet.x < -100) { enemyBullet.destroy(); game.enemyBullets.splice(eb, 1); continue; } // Oyuncuya çarptı mı? if (isCircleHit(enemyBullet, playerShip)) { // Patlama efekti (patlamaeffekt görseli ile) oyuncu gemisinin üstünde göster var explosion = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width || 140, height: playerShip.height || 100 }); game.addChild(explosion); tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { explosion.destroy(); } }); // Kalkan power-up aktifse ilk hasarı engelle if (activePowerUp === "shield" && playerShip._shielded) { playerShip._shielded = false; if (playerShip._shieldCircle) { tween(playerShip._shieldCircle, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { playerShip._shieldCircle.destroy(); playerShip._shieldCircle = null; } }); } var shieldHit = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width * 1.7, height: playerShip.height * 1.7 }); shieldHit.alpha = 0.5; shieldHit.color = 0x7cbb37; game.addChild(shieldHit); tween(shieldHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { shieldHit.destroy(); } }); // Hasarı engelle, can azalmasın } else { setPlayerHealth(playerHealth - 2); } if (playerHealth <= 0) { LK.showGameOver(); return; } enemyBullet.destroy(); game.enemyBullets.splice(eb, 1); continue; } } } // Boss varsa, ekranda merkeze kadar her yönde hareket ettir if (game.bossImg && game.bossBaseY !== undefined) { // --- BOSS MERMİSİ ATEŞLEME --- if (typeof game.bossBulletCooldown === "undefined") { game.bossBulletCooldown = 60 + Math.floor(Math.random() * 40); // 1-1.5 sn arası game.lastBossBulletTick = LK.ticks; if (!game.bossBullets) game.bossBullets = []; } // Boss 8 saniyede bir bossfire ateşlesin if (typeof game.lastBossFireTick === "undefined") { game.lastBossFireTick = LK.ticks; } // Bossfire ve bossmermi aynı anda ateşlenmesin var bossFireJustFired = false; // --- BOSS 2. FAZ: GÜÇLÜ SALDIRI --- // 2. fazdaysa, bossfire ve bossmermi saldırılarını güçlendir if (game.bossPhase === 2) { // Her 2 saniyede bir spiral/dalga bossmermi ve çoklu bossfire if (typeof game.bossPhase2AttackTick === "undefined") game.bossPhase2AttackTick = LK.ticks; if (typeof game.bossPhase2AttackInterval === "undefined") game.bossPhase2AttackInterval = 120; if (LK.ticks - game.bossPhase2AttackTick > game.bossPhase2AttackInterval) { // Spiral/dalga bossmermi (5 mermi, farklı açılar) var spiralCount = 5; var spiralBaseAngle = LK.ticks % 360 * Math.PI / 180; for (var s = 0; s < spiralCount; s++) { var angle = spiralBaseAngle + Math.PI * 2 / spiralCount * s; var bossBullet = LK.getAsset('bossmermi', { anchorX: 0.5, anchorY: 0.5, x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 40, y: game.bossImg.y, width: 48, height: 48 }); // Spiral hareket: hem sola hem açılı var speed = 11 + Math.random() * 2; bossBullet.vx = -speed * Math.cos(angle); bossBullet.vy = speed * Math.sin(angle) * 0.7; bossBullet.update = function (bullet) { return function () { bullet.x += bullet.vx; bullet.y += bullet.vy; }; }(bossBullet); if (!game.bossBullets) game.bossBullets = []; game.bossBullets.push(bossBullet); game.addChild(bossBullet); } // Çoklu bossfire (daha geniş yay, daha hızlı) var fireCount = 5; var spread = 220; for (var f = 0; f < fireCount; f++) { var offsetY = -spread / 2 + spread / (fireCount - 1) * f; var bossFire = LK.getAsset('bossfire', { anchorX: 0.5, anchorY: 0.5, x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 60, y: game.bossImg.y + offsetY, width: 90, height: 90 }); var speedFire = 16 + Math.random() * 2; bossFire.vx = -speedFire; bossFire.vy = 0; bossFire.burning = false; bossFire.burnTicks = 0; bossFire.update = function (fire) { return function () { fire.x += fire.vx; fire.y += fire.vy; if (fire.burning) { fire.alpha = 0.7 + 0.3 * Math.sin(LK.ticks / 4); } }; }(bossFire); if (!game.bossFires) game.bossFires = []; game.bossFires.push(bossFire); game.addChild(bossFire); } game.bossPhase2AttackTick = LK.ticks; bossFireJustFired = true; } } // 1. faz veya 2. fazda normal bossfire if (!bossFireJustFired && LK.ticks - game.lastBossFireTick > 480) { // 8 saniye (60fps*8=480) // Bossfire aynı anda birkaç kez ateşlensin var fireCount = 3 + Math.floor(Math.random() * 2); // 3 veya 4 tane var spread = 120; // Y ekseninde yayılma mesafesi for (var f = 0; f < fireCount; f++) { var offsetY = -spread / 2 + spread / (fireCount - 1) * f; var bossFire = LK.getAsset('bossfire', { anchorX: 0.5, anchorY: 0.5, x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 60, y: game.bossImg.y + offsetY, width: 80, height: 80 }); // Bossfire sadece sola doğru hareket etsin var speedFire = 13; // bossfire biraz hızlı gitsin bossFire.vx = -speedFire; bossFire.vy = 0; // Yanıcı (yakıcı) etki: çarptığında oyuncuya bir süre daha hasar vermeye devam etsin bossFire.burning = false; bossFire.burnTicks = 0; bossFire.update = function (fire) { return function () { fire.x += fire.vx; fire.y += fire.vy; // Yanıcı etki aktifse, görsel olarak hafif kırmızıya tintlenebilir (isteğe bağlı) if (fire.burning) { fire.alpha = 0.7 + 0.3 * Math.sin(LK.ticks / 4); } }; }(bossFire); if (!game.bossFires) game.bossFires = []; game.bossFires.push(bossFire); game.addChild(bossFire); } game.lastBossFireTick = LK.ticks; bossFireJustFired = true; } // Boss mermisi ateşle if (!bossFireJustFired && LK.ticks - game.lastBossBulletTick > game.bossBulletCooldown) { // Boss'un ateşleme slotları: üstten alta eşit aralıklı hizalı slotlar var slotCount = 5; var slotOffsets = []; var bossImgHeight = game.bossImg.height || 400; var slotSpacing = bossImgHeight / (slotCount + 1); for (var si = 0; si < slotCount; si++) { // slotlar boss görselinin üstünden altına eşit aralıklı var slotY = -bossImgHeight / 2 + slotSpacing * (si + 1); slotOffsets.push({ y: slotY, angle: 0 // düz gitsin, dağınık olmasın }); } for (var si = 0; si < slotOffsets.length; si++) { var slot = slotOffsets[si]; var bossBullet = LK.getAsset('bossmermi', { anchorX: 0.5, anchorY: 0.5, x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 40, y: game.bossImg.y + slot.y, width: 48, height: 48 }); // Boss mermileri sadece sola doğru gitsin var speed = 10; // Reduced boss bullet speed bossBullet.vx = -speed; bossBullet.vy = 0; bossBullet.update = function (bullet) { return function () { bullet.x += bullet.vx; bullet.y += bullet.vy; }; }(bossBullet); game.bossBullets.push(bossBullet); game.addChild(bossBullet); } game.lastBossBulletTick = LK.ticks; game.bossBulletCooldown = 60 + Math.floor(Math.random() * 40); } // Bossfire mermilerini güncelle ve çarpışma kontrolü if (game.bossFires) { for (var bf = game.bossFires.length - 1; bf >= 0; bf--) { var fire = game.bossFires[bf]; if (fire.update) fire.update(); // Ekran dışıysa sil if (fire.x < -150 || fire.x > 2048 + 150 || fire.y < -150 || fire.y > 2732 + 150) { fire.destroy(); game.bossFires.splice(bf, 1); continue; } // Oyuncuya çarptı mı? if (isCircleHit(fire, playerShip)) { // Eğer bossfire zaten yanıcı değilse, yanıcı etki başlat if (!fire.burning) { fire.burning = true; fire.burnTicks = 0; fire.burnMaxTicks = 90; // 1.5 saniye boyunca yanıcı etki (60fps*1.5) fire.burnDamageInterval = 18; // Her 0.3 saniyede bir hasar uygula fire.lastBurnDamageTick = LK.ticks; // Patlama efekti var bossFireHit = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width || 140, height: playerShip.height || 100 }); game.addChild(bossFireHit); tween(bossFireHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { bossFireHit.destroy(); } }); // Kalkan power-up aktifse ilk hasarı engelle if (activePowerUp === "shield" && playerShip._shielded) { playerShip._shielded = false; if (playerShip._shieldCircle) { tween(playerShip._shieldCircle, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { playerShip._shieldCircle.destroy(); playerShip._shieldCircle = null; } }); } var shieldHit = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width * 1.7, height: playerShip.height * 1.7 }); shieldHit.alpha = 0.5; shieldHit.color = 0x7cbb37; game.addChild(shieldHit); tween(shieldHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { shieldHit.destroy(); } }); // Hasarı engelle, can azalmasın } else { setPlayerHealth(playerHealth - 5); // bossfire hasarı 5 } if (playerHealth <= 0) { LK.showGameOver(); return; } } // Yanıcı etkiyi oyuncunun üstünde bırak, mermiyi hemen yok etme // Mermiyi ekranda bırak, yanıcı etki bitince yok edilecek continue; } // Yanıcı (yakıcı) bossfire oyuncunun üstündeyse, periyodik hasar uygula if (fire.burning) { fire.burnTicks++; // Her burnDamageInterval tick'te bir hasar uygula if (fire.burnTicks === 1 || fire.burnTicks % fire.burnDamageInterval === 0) { setPlayerHealth(playerHealth - 1); // Yanıcı efektin üstünde küçük bir alev efekti gösterebiliriz (isteğe bağlı) var burnEffect = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: 80, height: 80 }); burnEffect.alpha = 0.5; game.addChild(burnEffect); tween(burnEffect, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 200, onFinish: function onFinish() { burnEffect.destroy(); } }); if (playerHealth <= 0) { updateCanBar(); LK.showGameOver(); return; } } // Yanıcı etki süresi dolduysa bossfire'ı yok et if (fire.burnTicks > fire.burnMaxTicks) { fire.destroy(); game.bossFires.splice(bf, 1); continue; } } } } // Boss mermilerini güncelle ve çarpışma kontrolü for (var bb = game.bossBullets.length - 1; bb >= 0; bb--) { var bBullet = game.bossBullets[bb]; if (bBullet.update) bBullet.update(); // Ekran dışıysa sil if (bBullet.x < -100 || bBullet.x > 2048 + 100 || bBullet.y < -100 || bBullet.y > 2732 + 100) { bBullet.destroy(); game.bossBullets.splice(bb, 1); continue; } // Oyuncuya çarptı mı? if (isCircleHit(bBullet, playerShip)) { // Patlama efekti var bossBulletHit = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width || 140, height: playerShip.height || 100 }); game.addChild(bossBulletHit); tween(bossBulletHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { bossBulletHit.destroy(); } }); // Kalkan power-up aktifse ilk hasarı engelle if (activePowerUp === "shield" && playerShip._shielded) { playerShip._shielded = false; if (playerShip._shieldCircle) { tween(playerShip._shieldCircle, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { playerShip._shieldCircle.destroy(); playerShip._shieldCircle = null; } }); } var shieldHit = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width * 1.7, height: playerShip.height * 1.7 }); shieldHit.alpha = 0.5; shieldHit.color = 0x7cbb37; game.addChild(shieldHit); tween(shieldHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { shieldHit.destroy(); } }); // Hasarı engelle, can azalmasın } else { setPlayerHealth(playerHealth - 3); // bossmermi hasarı 3 } if (playerHealth <= 0) { LK.showGameOver(); return; } bBullet.destroy(); game.bossBullets.splice(bb, 1); continue; } } // Boss'un hareket yarıçapı: ekranın sağ yarısında, merkeze kadar gidebilsin // Merkez: (2048/2, 2732/2) // Boss'un hareket merkezi: ekranın sağında başlar, merkeze kadar hareket edebilir var centerX = 2048 / 2; var centerY = 2732 / 2; var rightEdgeX = 2048 - 200; var bossMoveRadiusX = (rightEdgeX - centerX) / 2; // sağdan merkeze kadar yarıçap var bossMoveRadiusY = (centerY - 0) * 0.8; // üstten alta merkeze kadar (biraz daha az) var bossCenterX = centerX + bossMoveRadiusX; var bossCenterY = centerY; // --- BOSS MERMİLERİNDEN KAÇMA ALGORİTMASI KALDIRILDI --- // Boss, ekrandaki boss mermilerinden kaçmaz, sadece dairesel hareket yapar var t = LK.ticks / 60; // yavaş hareket için var bossTargetX = bossCenterX + Math.cos(t) * bossMoveRadiusX; var bossTargetY = bossCenterY + Math.sin(t * 0.8) * bossMoveRadiusY; // Boss'un hedef pozisyonuna yumuşak geçiş (smooth movement) var lerp = function lerp(a, b, t) { return a + (b - a) * t; }; game.bossImg.x = lerp(game.bossImg.x, bossTargetX, 0.18); game.bossImg.y = lerp(game.bossImg.y, bossTargetY, 0.18); // --- BOSS CAN, HASAR ALMA, HASAR VERME --- // Boss canı başlat if (typeof game.bossHealth === "undefined") { game.bossMaxHealth = 30; // Boss'un toplam canı artık 30 (daha zor) game.bossHealth = game.bossMaxHealth; // Boss can barı game.bossHealthBarBg = new Container(); var bossBarBgRect = game.bossHealthBarBg.attachAsset('can', { anchorX: 0, anchorY: 0.5, x: 0, y: 20, width: 400, height: 40 }); bossBarBgRect.alpha = 0.25; game.bossHealthBarFg = new Container(); var bossBarFgRect = game.bossHealthBarFg.attachAsset('can', { anchorX: 0, anchorY: 0.5, x: 0, y: 20, width: 400, height: 40 }); bossBarFgRect.alpha = 1; game.bossHealthBarContainer = new Container(); game.bossHealthBarContainer.addChild(game.bossHealthBarBg); game.bossHealthBarContainer.addChild(game.bossHealthBarFg); // Boss can barı ekranın sağ üst köşesinde, timer'ın hemen altında göster game.bossHealthBarContainer.x = -400; // Offset for right alignment in gui.topRight game.bossHealthBarContainer.y = 100; // Just below timer LK.gui.topRight.addChild(game.bossHealthBarContainer); } // Boss can barını güncelle var bossTargetWidth = 400 * Math.max(0, game.bossHealth) / (game.bossMaxHealth || 30); tween(game.bossHealthBarFg.children[0], { width: bossTargetWidth }, { duration: 200 }); // Boss can barı rengi: yeşil (full) -> kırmızı (az) var bossHealthRatio = Math.max(0, Math.min(1, game.bossHealth / (game.bossMaxHealth || 30))); var br = Math.round(0xFF * (1 - bossHealthRatio)); var bg = Math.round(0xFF * bossHealthRatio); var bb = 0; var bossColor = br << 16 | bg << 8 | bb; tween(game.bossHealthBarFg.children[0], { color: bossColor }, { duration: 200 }); // Boss'a mermi çarpması kontrolü for (var bi = bullets.length - 1; bi >= 0; bi--) { var bossBullet = bullets[bi]; // Boss'un çarpışma yarıçapı: görselin yarısı var bossRadius = (game.bossImg.width || 400) / 2; var dx = bossBullet.x - game.bossImg.x; var dy = bossBullet.y - game.bossImg.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < bossRadius + 16) { // Patlama efekti var bossHit = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: bossBullet.x, y: bossBullet.y, width: 80, height: 80 }); game.addChild(bossHit); tween(bossHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 300, onFinish: function onFinish() { bossHit.destroy(); } }); // Boss canı azalt game.bossHealth -= 2; if (game.bossHealth < 0) game.bossHealth = 0; // --- BOSS 2. FAZ GEÇİŞİ --- // Faz geçişi sadece bir kez tetiklensin if (typeof game.bossPhase === "undefined") { game.bossPhase = 1; } if (game.bossPhase === 1 && game.bossHealth <= (game.bossMaxHealth || 30) / 2) { // 2. faza geçiş animasyonu ve güçlendirme game.bossPhase = 2; // Boss'u kısa süre dokunulmaz yap, renk değiştir, büyüt/küçült animasyonu if (game.bossImg) { // Kısa bir parlama ve büyüme/küçülme animasyonu var oldColor = game.bossImg.color; tween(game.bossImg, { scaleX: 1.35, scaleY: 1.35, alpha: 0.5, color: 0xff2e2e // Kırmızımsı bir renk }, { duration: 350, easing: tween.easeInOut, onFinish: function onFinish() { tween(game.bossImg, { scaleX: 1.0, scaleY: 1.0, alpha: 1, color: oldColor }, { duration: 350, easing: tween.easeInOut }); } }); // Kısa süreli dokunulmazlık (faz geçişi sırasında hasar almasın) game.bossInvulnerableTicks = 40; // ~0.7 saniye } // 2. faz için saldırı güçlendirmeleri game.bossPhase2AttackTick = LK.ticks; game.bossPhase2AttackInterval = 120; // Her 2 saniyede bir özel saldırı // Boss mermileri ve bossfire daha sık ve daha hızlı olacak game.bossBulletCooldown = 30 + Math.floor(Math.random() * 20); // Daha sık ateş } // Faz geçişi sırasında boss hasar almasın if (game.bossInvulnerableTicks && game.bossInvulnerableTicks > 0) { game.bossInvulnerableTicks--; // Mermiyi yok et ama boss canı azaltma bossBullet.destroy(); bullets.splice(bi, 1); continue; } // Boss öldü mü? if (game.bossHealth <= 0) { // Boss patlama efekti var bossExplosion = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: game.bossImg.x, y: game.bossImg.y, width: game.bossImg.width || 400, height: game.bossImg.height || 400 }); game.addChild(bossExplosion); tween(bossExplosion, { alpha: 0, scaleX: 3, scaleY: 3 }, { duration: 800, onFinish: function onFinish() { bossExplosion.destroy(); } }); // Boss'u yok et if (game.bossImg) { game.bossImg.destroy(); game.bossImg = null; } // Boss can barını yok et if (game.bossHealthBarContainer) { game.bossHealthBarContainer.destroy(); game.bossHealthBarContainer = null; } // Boss ile ilgili tüm mermileri ve ateşleri yok et if (game.bossBullets) { for (var bb = game.bossBullets.length - 1; bb >= 0; bb--) { if (game.bossBullets[bb]) game.bossBullets[bb].destroy(); } game.bossBullets = []; } if (game.bossFires) { for (var bf = game.bossFires.length - 1; bf >= 0; bf--) { if (game.bossFires[bf]) game.bossFires[bf].destroy(); } game.bossFires = []; } // Boss öldüğünde boss ile ilgili tüm objeleri yok et ve elmas puanını 10 arttır diamondCount += 10; updateDiamondCounter(); // Boss ile ilgili tüm objeleri yok et if (game.bossImg) { game.bossImg.destroy(); game.bossImg = null; } if (game.bossHealthBarContainer) { game.bossHealthBarContainer.destroy(); game.bossHealthBarContainer = null; } if (game.bossBullets) { for (var bb = game.bossBullets.length - 1; bb >= 0; bb--) { if (game.bossBullets[bb]) game.bossBullets[bb].destroy(); } game.bossBullets = []; } if (game.bossFires) { for (var bf = game.bossFires.length - 1; bf >= 0; bf--) { if (game.bossFires[bf]) game.bossFires[bf].destroy(); } game.bossFires = []; } // Boss diamond ve portal spawn işlemleri ve skor bonusu score += 20; scoreTxt.setText(score); updateDifficulty(); // --- BOSS ÖLDÜ: Elmas (diamond) spawn et, oyuncu toplarsa 10 elmas ver --- if (!game.bossDiamondSpawned) { // Elmas objesi ekranda bir kez spawn edilir, boss'un öldüğü yerde if (typeof bossDiamondObj === "undefined") bossDiamondObj = null; bossDiamondObj = LK.getAsset('diamond', { anchorX: 0.5, anchorY: 0.5, x: 2048 - 200, y: 2732 / 2, width: 120, height: 120 }); bossDiamondObj.alpha = 0.98; bossDiamondObj.vx = -2.5 + Math.random() * 5; // Hafif sağa/sola hareket bossDiamondObj.vy = -2 + Math.random() * 4; // Hafif yukarı/aşağı hareket bossDiamondObj.update = function () { bossDiamondObj.x += bossDiamondObj.vx; bossDiamondObj.y += bossDiamondObj.vy; // Ekran dışına çıkarsa yok et if (bossDiamondObj.x < -150 || bossDiamondObj.x > 2048 + 150 || bossDiamondObj.y < -150 || bossDiamondObj.y > 2732 + 150) { bossDiamondObj.destroy(); bossDiamondObj = null; return; } // Oyuncu toplarsa 10 elmas ver if (playerShip && isCircleHit(bossDiamondObj, playerShip)) { diamondCount += 10; updateDiamondCounter(); // Efekt: patlama var effect = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: bossDiamondObj.x, y: bossDiamondObj.y, width: 140, height: 140 }); effect.alpha = 0.8; game.addChild(effect); tween(effect, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { effect.destroy(); } }); bossDiamondObj.destroy(); bossDiamondObj = null; // Sadece bir kez alınabilsin game.bossDiamondSpawned = true; } }; game.addChild(bossDiamondObj); game.bossDiamondSpawned = false; // Henüz alınmadı } // --- High Score Save on Win --- addHighScore(score); // --- PORTAL EKLE --- if (!game.portal) { // Portalı ekranın sağında ortalanmış şekilde oluştur, ekran dışına taşmayacak şekilde var portalWidth = 120; var portalHeight = 120; var portalScale = 3.0; // Büyüme sonrası maksimum scale var portalX = 2048 - portalWidth * portalScale / 2 - 40; // Sağdan 40px boşluk bırak var portalY = 2732 / 2; var portal = LK.getAsset('portal', { anchorX: 0.5, anchorY: 0.5, x: portalX, y: portalY, width: portalWidth, height: portalHeight }); portal.scaleX = 1.2; portal.scaleY = 1.2; portal.alpha = 1; portal.isShrinking = false; portal.lastWasIntersecting = false; game.portal = portal; game.addChild(portal); // Portal büyüme animasyonu: 1.2'den 3.0'a kadar büyüsün portal._growTweenStarted = true; tween(portal, { scaleX: 3.0, scaleY: 3.0 }, { duration: 1200, easing: tween.easeOut, onFinish: function onFinish() { portal._growTweenStarted = false; // --- EKRAN DARALTMA: Boss öldükten sonra üstten ve alttan siyah barlar gelsin --- if (!game._screenNarrowed) { // Bar yüksekliği: toplam 600px (üst 300, alt 300) gibi, animasyonlu gelsin var barHeight = 0; var targetBarHeight = 300; // Üst bar var topBar = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 1 }); topBar.alpha = 0.95; topBar.color = 0x000000; // Alt bar var bottomBar = LK.getAsset('background', { anchorX: 0, anchorY: 1, x: 0, y: 2732, width: 2048, height: 1 }); bottomBar.alpha = 0.95; bottomBar.color = 0x000000; // Ekrana ekle game.addChild(topBar); game.addChild(bottomBar); // Animasyonla barları büyüt tween(topBar, { height: targetBarHeight }, { duration: 900, easing: tween.easeInOut }); tween(bottomBar, { height: targetBarHeight, y: 2732 - targetBarHeight }, { duration: 900, easing: tween.easeInOut }); // Oyun alanı sınırlarını daraltmak için global değişken game._screenNarrowed = true; game._topBar = topBar; game._bottomBar = bottomBar; // Oyun alanı sınırlarını güncelle (handleMove ve diğer kontrollerde kullanılabilir) game._playAreaTop = targetBarHeight; game._playAreaBottom = 2732 - targetBarHeight; } } }); } // Oyun bitmesin, win popup gösterme return; } } } // Boss oyuncuya çarparsa hasar versin if (playerShip && game.bossImg) { var dxp = playerShip.x - game.bossImg.x; var dyp = playerShip.y - game.bossImg.y; var distp = Math.sqrt(dxp * dxp + dyp * dyp); var bossRadius = (game.bossImg.width || 400) / 2; var playerRadius = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70); if (distp < bossRadius + playerRadius - 20) { // Sadece ilk çarpışmada hasar uygula (her frame değil) if (!game.bossLastPlayerHit) { // Patlama efekti var bossPlayerHit = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: playerShip.x, y: playerShip.y, width: playerShip.width || 140, height: playerShip.height || 100 }); game.addChild(bossPlayerHit); tween(bossPlayerHit, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { bossPlayerHit.destroy(); } }); setPlayerHealth(playerHealth - 5); if (playerHealth <= 0) { LK.showGameOver(); return; } game.bossLastPlayerHit = true; } } else { game.bossLastPlayerHit = false; } } } // (Geri alındı: scrollX += scrollSpeed ile sağa doğru ilerleme efekti yok) // --- Ava: playerShip ve portal da scrollX ile sağa kaymalı (otomatik hareket yoksa) --- // (Geri alındı: playerShip ve portal scrollSpeed ile sağa kaydırılmıyor) // Portal dinamik efekt: sadece büyüme ve renk döngüsü (nabız efekti kaldırıldı) if (game.portal) { // Portal'ın konumu ve büyümesi: portal ekranın tam ortasında sabit kalır, büyüme animasyonu yok if (game.portal) { // Renk döngüsü (HSV'den RGB'ye basit dönüşüm) var t = LK.ticks % 360 / 360; var h = t, s = 0.7, v = 1.0; var i = Math.floor(h * 6); var f = h * 6 - i; var p = v * (1 - s); var q = v * (1 - f * s); var r, g, b; switch (i % 6) { case 0: r = v, g = q, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = q; break; case 3: r = p, g = q, b = v; break; case 4: r = q, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } var color = Math.round(r * 255) << 16 | Math.round(g * 255) << 8 | Math.round(b * 255); game.portal.color = color; } if (typeof game.portal.isShrinking === "undefined") game.portal.isShrinking = false; if (typeof game.portal.lastWasIntersecting === "undefined") game.portal.lastWasIntersecting = false; // --- Portal büyümesi bittikten sonra playership otomatik geçişi için ek kodlar --- if (game.portal && !game.portal.isShrinking && !game.portal._autoMoveStarted && !game.portal.lastWasIntersecting) { // Portal büyüme animasyonu bittiyse (scaleX >= 3.0 - 0.01) if (!game.portal._growTweenStarted && Math.abs(game.portal.scaleX - 3.0) < 0.01 && playerShip && !playerShip._autoMovingToPortal) { // Otomatik hareket başlatılmadan önce 2 saniye bekle game.portal._autoMoveStarted = true; playerShip._autoMovingToPortal = true; // Hedef portalın merkezi var portalTargetX = game.portal.x; var portalTargetY = game.portal.y; LK.setTimeout(function () { // 2 saniye sonra otomatik hareket başlasın tween(playerShip, { x: portalTargetX, y: portalTargetY }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { // Hareket bittiğinde flag kaldır playerShip._autoMovingToPortal = false; } }); }, 2000); } } // Oyuncu gemisi portal ile temas etti mi? var portalIntersect = false; if (playerShip && !game.portal.isShrinking) { // Portal ve gemi çarpışma kontrolü (daire-çarpışma) var dx = playerShip.x - game.portal.x; var dy = playerShip.y - game.portal.y; var portalRadius = (game.portal.width ? game.portal.width / 2 : 60) * game.portal.scaleX; var playerRadius = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70); var dist = Math.sqrt(dx * dx + dy * dy); portalIntersect = dist < portalRadius + playerRadius - 10; if (!game.portal.lastWasIntersecting && portalIntersect) { // Gemi portalın içine girdi: gemi ve mermiler kaybolsun, portal küçülüp ışık patlamasıyla kaybolsun // Gemi kaybolsun (görsel olarak) if (playerShip && playerShip.parent) { tween(playerShip, { alpha: 0, scaleX: 0.2, scaleY: 0.2 }, { duration: 400, onFinish: function onFinish() { if (playerShip && playerShip.parent) { playerShip.destroy(); } } }); } // Tüm mermileri kaybolma animasyonuyla yok et for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; if (b && b.parent) { b.visible = false; // Portal geçildikten sonra mermiler görünmesin b.alpha = 0; b.destroy(); } } bullets = []; // Portal küçülmeye başlasın game.portal.isShrinking = true; tween(game.portal, { scaleX: 0.1, scaleY: 0.1, alpha: 0.0 }, { duration: 900, easing: tween.easeIn, onFinish: function onFinish() { // Işık patlaması efekti if (game.portal && game.portal.parent) { var portalExplosion = LK.getAsset('portalblast', { anchorX: 0.5, anchorY: 0.5, x: game.portal.x, y: game.portal.y, width: (game.portal.width || 120) * (game.portal.scaleX || 1.0) * 2.2, height: (game.portal.height || 120) * (game.portal.scaleY || 1.0) * 2.2 }); portalExplosion.alpha = 0.85; game.addChild(portalExplosion); tween(portalExplosion, { alpha: 0, scaleX: 2.5, scaleY: 2.5 }, { duration: 500, onFinish: function onFinish() { if (portalExplosion && portalExplosion.parent) portalExplosion.destroy(); // Portal tamamen kaybolduktan sonra win ekranı göster // LK.showYouWin(); // Win ekranı gösterme KALDIRILDI } }); game.portal.destroy(); game.portal = null; } } }); } game.portal.lastWasIntersecting = portalIntersect; } } // Kara delik (BlackHole) özelliği kaldırıldı // --- Nadiren çıkan diamond objesi için global değişken ve spawn sistemi --- if (typeof diamondObj === "undefined") diamondObj = null; if (typeof lastDiamondSpawnTick === "undefined") lastDiamondSpawnTick = -10000; var diamondSpawnCooldown = 3600 + Math.floor(Math.random() * 1800); // 1-1.5 dakika arası (60fps*60=3600) if (!diamondObj && LK.ticks - lastDiamondSpawnTick > diamondSpawnCooldown) { // %7 olasılıkla diamond spawn et (çok nadir) if (Math.random() < 0.07) { diamondObj = LK.getAsset('diamond', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 600 + Math.random() * 400 - 200, y: 400 + Math.random() * (2732 - 800), width: 100, height: 100 }); diamondObj.alpha = 0.95; diamondObj.vx = -3 - Math.random() * 2.5; diamondObj.vy = (Math.random() - 0.5) * 2.0; diamondObj.update = function () { diamondObj.x += diamondObj.vx; diamondObj.y += diamondObj.vy; // Ekran dışına çıkarsa yok et if (diamondObj.x < -150 || diamondObj.x > 2048 + 150 || diamondObj.y < -150 || diamondObj.y > 2732 + 150) { diamondObj.destroy(); diamondObj = null; return; } }; game.addChild(diamondObj); lastDiamondSpawnTick = LK.ticks; } else { // spawn denemesi başarısızsa tekrar denemek için tick'i güncelleme lastDiamondSpawnTick = LK.ticks; } } // Gift spawn: gift yoksa ve spawn süresi dolduysa nadiren spawn et // OYUNUN BAŞINDA HEDİYE/ÖDÜL VERİLMEZ: ilk 10 saniye (600 tick) ödül yok var minGiftSpawnTick = 600; // 10 saniye (60fps*10) if (LK.ticks <= minGiftSpawnTick) { // İlk 10 saniye ödül/gift/diamond verilmeyecek } else if (!giftBg && LK.ticks - lastGiftSpawnTick > giftSpawnCooldown && LK.ticks > minGiftSpawnTick) { // Rastgele olasılıkla gift spawn et (ör: %60 olasılık) if (Math.random() < 0.6) { spawnGift(); } else { // spawn denemesi başarısızsa tekrar denemek için tick'i güncelleme lastGiftSpawnTick = LK.ticks; } } // Gift güncellemesi (power-up çarpışma kontrolü) if (giftBg && giftBg.update) { giftBg.update(); } // Diamond objesi güncellemesi if (diamondObj && diamondObj.update) { diamondObj.update(); } // Boss öldüğünde çıkan diamond objesi güncellemesi if (typeof bossDiamondObj !== "undefined" && bossDiamondObj && bossDiamondObj.update) { bossDiamondObj.update(); } // Aktif power-up süresini kontrol et if (activePowerUp && LK.ticks >= powerUpEndTick) { deactivatePowerUp(); } // Power-up efektleri: hız, kalkan, skor çarpanı if (activePowerUp === "speedup" && playerShip && dragging) { // Sürükleme hızını artırmak için handleMove fonksiyonunda hız limiti artırılabilir // (Burada ek bir kod gerekmez, handleMove zaten sınırları kontrol ediyor) } if (activePowerUp === "shield" && playerShip && playerShip._shieldCircle) { // Kalkan efekti: hafif nabız animasyonu var t = LK.ticks % 60 / 60; var scale = 1.3 + 0.1 * Math.sin(t * Math.PI * 2); playerShip._shieldCircle.scaleX = scale; playerShip._shieldCircle.scaleY = scale; } // Power-up skor çarpanı: skor eklenirken game._scoreMultiplier kullanılır if (!game._scoreMultiplier) game._scoreMultiplier = 1; // --- Orijinal kod --- };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScores: []
});
/****
* Classes
****/
// Asteroid - SAĞDAN SOLA
var Asteroid = Container.expand(function () {
var self = Container.call(this);
var width = 120 + Math.random() * 60;
var height = 120 + Math.random() * 60;
var objAsset = self.attachAsset('spaceObject', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
objAsset.color = 0x888888;
self.radius = width / 2;
// Always spawn at right edge, random Y, move left
self.x = 2048 + width;
self.y = 200 + Math.random() * (2732 - 400);
// Dynamic spawn effect: scale up and fade in
self.scaleX = 0.6;
self.scaleY = 0.6;
self.alpha = 0.0;
tween(self, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
// Speed will be set on spawn
self.vx = -12;
self.vy = (Math.random() - 0.5) * 2;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Mermi (Bullet) - SAĞA DOĞRU
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Asset: ellipse, width: 32, height: 32, color: 0xffe066
bulletAsset.width = 32;
bulletAsset.height = 32;
bulletAsset.color = 0xffe066;
self.speed = typeof game !== "undefined" && game._bulletSpeedUp ? 38 : 22; // bulletspeed power-up aktifse daha hızlı, normalde biraz daha hızlı
// Dynamic spawn effect: scale up and fade in
self.scaleX = 0.5;
self.scaleY = 0.5;
self.alpha = 0.0;
tween(self, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 200,
easing: tween.easeOut
});
self.update = function () {
self.x += self.speed;
};
return self;
});
// EnemyBullet - DÜŞMAN MERMİSİ (sola doğru)
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('dusmanmermi', {
anchorX: 0.5,
anchorY: 0.5
});
bulletAsset.width = 32;
bulletAsset.height = 32;
bulletAsset.color = 0xff4444;
self.speed = -16; // Sola doğru (daha hızlı)
// Dynamic spawn effect: scale up and fade in
self.scaleX = 0.5;
self.scaleY = 0.5;
self.alpha = 0.0;
tween(self, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 200,
easing: tween.easeOut
});
self.update = function () {
self.x += self.speed;
};
return self;
});
// EnemyShip - SAĞDAN SOLA
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var width = 100;
var height = 100;
var objAsset = self.attachAsset('uzayNesnesi2', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
objAsset.color = 0xff4444;
self.radius = width / 2;
self.x = 2048 + width;
self.y = 200 + Math.random() * (2732 - 400);
// Dynamic spawn effect: scale up and fade in
self.scaleX = 0.6;
self.scaleY = 0.6;
self.alpha = 0.0;
tween(self, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
// Speed will be set on spawn
self.vx = -14;
self.vy = (Math.random() - 0.5) * 3;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// MeteorStone - SAĞDAN SOLA, rastgele gelen düşman türü
var MeteorStone = Container.expand(function () {
var self = Container.call(this);
var width = 120 + Math.random() * 60;
var height = 120 + Math.random() * 60;
var objAsset = self.attachAsset('meteorstone', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
self.radius = width / 2;
// Always spawn at right edge, random Y, move left
self.x = 2048 + width;
self.y = 200 + Math.random() * (2732 - 400);
// Dynamic spawn effect: scale up and fade in
self.scaleX = 0.6;
self.scaleY = 0.6;
self.alpha = 0.0;
tween(self, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
// Hız: asteroidlerden biraz daha hızlı olabilir
var baseSpeed = 5 + Math.random() * 2.5;
self.vx = -baseSpeed;
self.vy = (Math.random() - 0.5) * 2.5;
self.update = function () {
// Oyuncu gemisi varsa ona doğru yönel
if (typeof playerShip !== "undefined" && playerShip && typeof playerShip.x === "number" && typeof playerShip.y === "number") {
var dx = playerShip.x - self.x;
var dy = playerShip.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Hedefe doğru normalize edilmiş hız vektörü
if (dist > 1) {
var speed = Math.sqrt(self.vx * self.vx + self.vy * self.vy);
// Hız sabit kalsın, sadece yön değişsin
var nx = dx / dist;
var ny = dy / dist;
self.vx += (nx * speed - self.vx) * 0.08; // yumuşak yön değiştirme
self.vy += (ny * speed - self.vy) * 0.08;
}
}
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Uzay Aracı (Player Ship)
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
// Ship asset: blue ellipse
var shipAsset = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Asset will be created as: ellipse, width: 140, height: 100, color: 0x3a9cff
shipAsset.width = 140;
shipAsset.height = 100;
shipAsset.color = 0x3a9cff;
self.radius = 70; // For collision
self.update = function () {
// Otomatik sağa ilerleme kaldırıldı, sadece otomatik portal hareketi sırasında hareket etsin
};
return self;
});
// Uzay Cismi (Asteroid/Enemy) - SAĞDAN SOLA
var SpaceObject = Container.expand(function () {
var self = Container.call(this);
// Randomly choose asteroid or enemy
var isAsteroid = Math.random() < 0.7;
var color = isAsteroid ? 0x888888 : 0xff4444;
var width = isAsteroid ? 120 + Math.random() * 60 : 100;
var height = isAsteroid ? 120 + Math.random() * 60 : 100;
var objAsset = self.attachAsset('spaceObject', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
objAsset.color = color;
self.radius = width / 2;
// Always spawn at right edge, random Y, move left
self.x = 2048 + width;
self.y = 200 + Math.random() * (2732 - 400);
// Dynamic spawn effect: scale up and fade in
self.scaleX = 0.6;
self.scaleY = 0.6;
self.alpha = 0.0;
tween(self, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
var speed = 9 + Math.random() * 5;
self.vx = -speed;
self.vy = (Math.random() - 0.5) * 2; // hafif yukarı/aşağı varyasyon
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
/****
* Initialize Game
****/
// Create and add stars to the background
var game = new LK.Game({
backgroundColor: 0x000010
});
/****
* Game Code
****/
// Galaksi arka planı kaldırıldı
// Yıldızlar: Parallax ve hafif dönen yıldızlar
var starBgCount = 90;
var stars = [];
var starBgContainer = new Container();
for (var i = 0; i < starBgCount; i++) {
var starSize = 2 + Math.random() * 4;
var star = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: Math.random() * 2732,
width: starSize,
height: starSize
});
// Farklı parlaklıklar
star.alpha = 0.3 + Math.random() * 0.7;
// Farklı hızlar (parallax)
star._vx = 0.7 + Math.random() * 1.2;
// Hafif döndürme efekti
star._rotSpeed = (Math.random() - 0.5) * 0.01;
stars.push(star);
starBgContainer.addChild(star);
}
game.addChild(starBgContainer); // Yıldız arka planı ekle (addChildAt yerine addChild ile, out of bounds hatasını önler)
// --- BAŞLANGIÇ MENÜSÜ ---
var startMenuContainer = new Container();
// Oyun başı intro sahnesi kaldırıldı, menü doğrudan gösteriliyor
if (!startMenuContainer.parent) {
startMenuContainer.alpha = 1;
startMenuContainer.scaleX = 1;
startMenuContainer.scaleY = 1;
game.addChild(startMenuContainer);
}
// Menü renklerini dinamik olarak yönetmek için global değişkenler
var menuBgColor = 0x181c2b;
var menuButtonColors = [0x3a9cff, 0x4e5d94, 0x7cbb37, 0xf7b32b];
var menuWidth = 1000;
var menuHeight = 1100;
// Menü arka planına renkli kutu ekle (görsel yerine)
var startMenuBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: menuHeight / 2,
width: menuWidth,
height: menuHeight
});
startMenuBg.alpha = 0.0; // Tamamen şeffaf yap
startMenuBg.color = menuBgColor;
startMenuContainer.addChild(startMenuBg);
// Menü arka planına border efekti kaldırıldı (menu image ile uyumlu)
// Başlık ve alt başlık
var titleText = new Text2("UZAY MACERASI", {
size: 120,
fill: 0xFFE066
});
titleText.anchor.set(0.5, 0.5);
titleText.x = menuWidth / 2;
titleText.y = 140;
startMenuContainer.addChild(titleText);
// Subtitle text removed as requested
// Dinamik butonlar
var menuButtons = [{
label: "Yeni Oyun",
key: "start",
color: 0x3a9cff
}, {
label: "Mağaza",
key: "options",
color: 0x4e5d94
}, {
label: "Rekorlar",
key: "scores",
color: 0x7cbb37
}, {
label: "Hakkında",
key: "about",
color: 0xf7b32b
}];
var buttonHeight = 140;
var buttonWidth = 600;
var buttonSpacing = 48;
var firstBtnY = 400;
var btnBgList = [];
var btnTextList = [];
for (var i = 0; i < menuButtons.length; i++) {
var btnY = firstBtnY + i * (buttonHeight + buttonSpacing);
// Butonun arka planı (hafif gölgeli, modern)
var btnBgShadow = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2 + 8,
y: btnY + 10,
width: buttonWidth + 24,
height: buttonHeight + 18
});
btnBgShadow.alpha = 0.18;
btnBgShadow.color = 0x000000;
startMenuContainer.addChild(btnBgShadow);
var btnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: btnY,
width: buttonWidth,
height: buttonHeight
});
btnBg.alpha = 0.92;
btnBg.color = menuButtonColors[i % menuButtonColors.length];
btnBg.menuKey = menuButtons[i].key;
btnBg.buttonIndex = i;
btnBg.interactive = true; // Buton tıklanabilir olsun
btnBg.defaultAlpha = btnBg.alpha; // Tıklama efekti için orijinal alpha
btnBg.down = function (btn) {
return function (x, y, obj) {
// Tıklama efekti: sadece bu buton için kısa bir görsel geri bildirim uygula
btn.alpha = 0.65;
tween(btn, {
alpha: btn.defaultAlpha
}, {
duration: 120
});
// Her butonun kendi işlevi
if (btn.menuKey === "start") {
// Menü animasyonla kaybolsun ve oyun başlasın
tween(startMenuContainer, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 350,
onFinish: function onFinish() {
if (startMenuContainer && startMenuContainer.parent) startMenuContainer.destroy();
// Oyun başladığında süreyi 3 dakikaya (180 saniye) sıfırla
timeLeft = gameDuration;
updateTimerDisplay();
gameStarted = true;
}
});
} else {
// Her menü butonu için yeni bir ekran (modal) aç
// Ana menü ekranını gizle
if (startMenuContainer && startMenuContainer.parent) {
startMenuContainer.visible = false;
}
var modalW = 1200;
var modalH = 1000;
var modalContainer = new Container();
var modalBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: modalH / 2,
width: modalW,
height: modalH
});
modalBg.alpha = 0.0; // Tamamen şeffaf yap
modalBg.color = 0x181c2b;
modalContainer.addChild(modalBg);
var modalTitle = "";
var modalContent = "";
if (btn.menuKey === "options") {
modalTitle = "Mağaza";
modalContent = "";
// Satın alınabilir ürünler
var storeProducts = [];
// Ürünleri listele ve satın al butonları ekle
var productBtnH = 110;
var productBtnW = 600;
var productBtnSpacing = 24;
var firstProductY = 260;
for (var p = 0; p < storeProducts.length; p++) {
var prod = storeProducts[p];
var prodY = firstProductY + p * (productBtnH + productBtnSpacing);
// Ürün kutusu
var prodBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: prodY,
width: productBtnW,
height: productBtnH
});
prodBg.alpha = 0.0; // Tamamen şeffaf yap
prodBg.color = 0x232a3d;
modalContainer.addChild(prodBg);
// Ürün açıklaması (isim kaldırıldığı için üstte hizalanacak)
var prodDesc = new Text2(prod.desc, {
size: 36,
fill: 0xB0E0FF,
maxWidth: productBtnW - 220
});
// Açıklamayı butonun üstüne hizala
prodDesc.anchor.set(0, 1);
prodDesc.x = modalW / 2 - productBtnW / 2 + 32;
prodDesc.y = prodY - productBtnH / 2 + 18;
modalContainer.addChild(prodDesc);
// Fiyat etiketi
var priceTag = new Text2(prod.price + " 💎", {
size: 44,
fill: 0xFFE066
});
priceTag.anchor.set(1, 0.5);
priceTag.x = modalW / 2 + productBtnW / 2 - 120;
priceTag.y = prodY;
modalContainer.addChild(priceTag);
// Satın al butonu
var buyBtn = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2 + productBtnW / 2 - 60,
y: prodY,
width: 100,
height: 80
});
buyBtn.alpha = 0.85;
buyBtn.color = 0x3a9cff; // Mavi ton, kırmızı arka plan kaldırıldı
buyBtn.interactive = true;
buyBtn.down = function (prod, buyBtnRef) {
return function (x, y, obj) {
// Satın alma işlemi (örnek: elmas bakiyesi yok, sadece görsel feedback)
buyBtnRef.alpha = 0.65;
tween(buyBtnRef, {
alpha: 0.85
}, {
duration: 120
});
// Satın alma bildirimi
var boughtText = new Text2("Satın alındı!", {
size: 44,
fill: 0x7CBB37
});
boughtText.anchor.set(0.5, 0.5);
boughtText.x = buyBtnRef.x;
boughtText.y = buyBtnRef.y - 60;
modalContainer.addChild(boughtText);
tween(boughtText, {
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
boughtText.destroy();
}
});
};
}(prod, buyBtn);
modalContainer.addChild(buyBtn);
// Satın al butonu yazısı
var buyBtnText = new Text2("Satın Al", {
size: 36,
fill: "#fff"
});
buyBtnText.anchor.set(0.5, 0.5);
buyBtnText.x = buyBtn.x;
buyBtnText.y = buyBtn.y;
buyBtnText.interactive = true;
buyBtnText.down = function (buyBtnRef) {
return function (x, y, obj) {
if (buyBtnRef && buyBtnRef.down) buyBtnRef.down(x, y, obj);
};
}(buyBtn);
modalContainer.addChild(buyBtnText);
}
} else if (btn.menuKey === "scores") {
modalTitle = "Rekorlar";
// --- High Scores Modal Content ---
var scoresArr = getHighScores();
if (scoresArr.length === 0) {
modalContent = "Henüz rekor yok!";
} else {
modalContent = "En Yüksek 5 Skor:\n";
for (var s = 0; s < scoresArr.length; s++) {
modalContent += s + 1 + ". " + scoresArr[s] + "\n";
}
}
} else if (btn.menuKey === "about") {
modalTitle = "Hakkında";
modalContent = "Uzay Macerası - FRVR.Ava.Combo[POGAAS].v1.0";
}
var modalTitleText = new Text2(modalTitle, {
size: 100,
fill: 0xFFE066,
maxWidth: modalW - 80 // kutu kenarından taşmasın
});
modalTitleText.anchor.set(0.5, 0.5);
modalTitleText.x = modalW / 2;
modalTitleText.y = 120;
modalContainer.addChild(modalTitleText);
// --- 3x3 Kare Slotlar: Mağaza başlığı ile kapat tuşu arasına ---
// Sadece mağaza menüsünde slotlar görünsün
if (btn.menuKey === "options") {
// Kare slotlar için parametreler
var slotSize = 280; // Daha büyük slotlar
var slotSpacing = 64; // Slotlar arası biraz daha fazla boşluk
var slotsPerRow = 3;
var slotsPerCol = 1; // Artık sadece 1 satır olacak
// Slotların başlık ile kapat tuşu arasında ortalanması ve kapat tuşu ile çakışmaması için Y konumunu ayarla
// Kapat tuşu modalın en altında, slotlar başlığın hemen altından başlasın ve slotların altı ile kapat tuşu arasında yeterli boşluk kalsın
var slotsTotalWidth = slotsPerRow * slotSize + (slotsPerRow - 1) * slotSpacing;
var slotsTotalHeight = slotSize; // Sadece 1 satır
var closeBtnH = 100;
var closeBtnY = modalH - closeBtnH / 2 - 24;
// Slotları modalın ortasına dikeyde ortala, başlık ile kapat tuşu arasında
var availableHeight = closeBtnY - (modalTitleText.y + 120) - 40;
var slotsStartY = modalTitleText.y + 120 + Math.max(0, (availableHeight - slotsTotalHeight) / 2);
// Slotları yatayda tam merkeze hizala
var slotsStartX = modalW / 2 - slotsTotalWidth / 2 + slotSize / 2;
var slotList = [];
for (var row = 0; row < slotsPerCol; row++) {
for (var col = 0; col < slotsPerRow; col++) {
var slotX = slotsStartX + col * (slotSize + slotSpacing);
var slotY = slotsStartY + row * (slotSize + slotSpacing);
var slot = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: slotY,
width: slotSize,
height: slotSize
});
slot.alpha = 0.18;
slot.color = 0xB0E0FF;
modalContainer.addChild(slot);
slotList.push(slot);
// İlk slot ise playership2 görselini ortala ve sığdır
if (row === 0 && col === 0) {
// slotSize'ın %86'sı kadar bir kareye sığdır
var ps2Margin = 0.07 * slotSize;
var ps2Size = slotSize - 2 * ps2Margin;
var ps2 = LK.getAsset('playership2', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: slotY,
width: ps2Size,
height: ps2Size
});
ps2.alpha = 1;
modalContainer.addChild(ps2);
}
// 2. slot ise playership3 görselini ortala ve sığdır
if (row === 0 && col === 1) {
var ps3Margin = 0.07 * slotSize;
var ps3Size = slotSize - 2 * ps3Margin;
var ps3 = LK.getAsset('playership3', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: slotY,
width: ps3Size,
height: ps3Size
});
ps3.alpha = 1;
modalContainer.addChild(ps3);
}
// Satın Al butonu ekle (her slotun altına)
// Fiyat etiketleri: örnek olarak her slot için farklı fiyatlar
var slotPrices = [100, 250, 0]; // 3. slot yakında olduğu için fiyat 0
var buyBtnW = 180;
var buyBtnH = 90;
var buyBtnY = slotY + slotSize / 2 + 44;
var priceLabelY = buyBtnY + buyBtnH / 2 + 16;
var price = slotPrices[col];
// Fiyat etiketi: Satın al butonunun hemen altına
if (row === 0 && col === 2) {
// 3. slotun satın al butonu pasif olsun
var buyBtn = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: buyBtnY,
width: buyBtnW,
height: buyBtnH
});
buyBtn.alpha = 0.45;
buyBtn.color = 0x888888;
buyBtn.interactive = false;
// Butonun üstüne "Satın Al" yazısı (gri ve pasif)
var buyBtnText = new Text2("Satın Al", {
size: 32,
fill: "#bbb"
});
buyBtnText.anchor.set(0.5, 0.5);
buyBtnText.x = buyBtn.x;
buyBtnText.y = buyBtn.y;
modalContainer.addChild(buyBtnText);
// Fiyat etiketi (gri, pasif)
var priceText = new Text2("-", {
size: 28,
fill: "#bbb"
});
priceText.anchor.set(0.5, 0);
priceText.x = slotX;
priceText.y = priceLabelY;
modalContainer.addChild(priceText);
// 3. slotun altına "Yakında" yazısı ekle
var yakindaText = new Text2("Yakında", {
size: 32,
fill: 0xFFE066
});
yakindaText.anchor.set(0.5, 0);
yakindaText.x = slotX;
yakindaText.y = priceLabelY + 38;
modalContainer.addChild(yakindaText);
} else {
var buyBtn = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: buyBtnY,
width: buyBtnW,
height: buyBtnH
});
buyBtn.alpha = 0.92;
buyBtn.color = 0x3a9cff;
buyBtn.interactive = true;
buyBtn.defaultAlpha = buyBtn.alpha;
buyBtn.down = function (btnRef, price) {
return function (x, y, obj) {
btnRef.alpha = 0.65;
tween(btnRef, {
alpha: btnRef.defaultAlpha
}, {
duration: 120
});
// Elmas kontrolü: yeterli elmas yoksa satın alma başarısız
if (diamondCount < price) {
var failText = new Text2("Yetersiz elmas!", {
size: 36,
fill: 0xf75b5b
});
failText.anchor.set(0.5, 0.5);
failText.x = btnRef.x;
failText.y = btnRef.y - 48;
modalContainer.addChild(failText);
tween(failText, {
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
failText.destroy();
}
});
return;
}
// Elmasları harca
diamondCount -= price;
updateDiamondCounter();
// Satın alındı bildirimi
var boughtText = new Text2("Satın alındı!", {
size: 36,
fill: 0x7CBB37
});
boughtText.anchor.set(0.5, 0.5);
boughtText.x = btnRef.x;
boughtText.y = btnRef.y - 48;
modalContainer.addChild(boughtText);
tween(boughtText, {
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
boughtText.destroy();
}
});
// Burada price değişkeni ile satın alma işlemi yapılabilir
// Örn: satın alma işlemi için price değerini kullan
};
}(buyBtn, price);
modalContainer.addChild(buyBtn);
// Butonun üstüne "Satın Al" yazısı
var buyBtnText = new Text2("Satın Al", {
size: 32,
fill: "#fff"
});
buyBtnText.anchor.set(0.5, 0.5);
buyBtnText.x = buyBtn.x;
buyBtnText.y = buyBtn.y;
buyBtnText.interactive = true;
buyBtnText.down = function (btnRef) {
return function (x, y, obj) {
if (btnRef && btnRef.down) btnRef.down(x, y, obj);
};
}(buyBtn);
modalContainer.addChild(buyBtnText);
// Fiyat etiketi: Satın al butonunun hemen altına
// Fiyat etiketi: sembolü + fiyat
var priceText = new Text2("💎 " + price, {
size: 38,
fill: 0xFFE066
});
priceText.anchor.set(0.5, 0);
priceText.x = slotX;
priceText.y = priceLabelY + 24;
modalContainer.addChild(priceText);
}
}
}
}
var modalContentText = new Text2(modalContent, {
size: 60,
fill: "#fff",
maxWidth: modalW - 80 // kutu kenarından taşmasın
});
modalContentText.anchor.set(0.5, 0);
// İçerik, slotların hemen altına gelsin ve slotlarla çakışmasın
// Slotların altı ile kapat tuşu arasında yeterli boşluk bırak
var contentMinY = slotsStartY + slotsPerCol * slotSize + (slotsPerCol - 1) * slotSpacing + 32;
var contentMaxY = closeBtnY - closeBtnH / 2 - 40;
modalContentText.y = Math.min(contentMinY, contentMaxY);
modalContentText.x = modalW / 2;
modalContainer.addChild(modalContentText);
// Kapat butonu
var closeBtnW = 320;
var closeBtnH = 100;
// Move close button to the very bottom of the modal
var closeBtnY = modalH - closeBtnH / 2 - 24;
// Modern gradient effect: use two overlapping containers with different colors and alpha for a faux-gradient
var closeBtnBgBase = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: closeBtnY,
width: closeBtnW,
height: closeBtnH
});
closeBtnBgBase.alpha = 0.95;
closeBtnBgBase.color = 0x232a3d; // dark base
modalContainer.addChild(closeBtnBgBase);
var closeBtnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: closeBtnY,
width: closeBtnW,
height: closeBtnH
});
closeBtnBg.alpha = 0.92;
closeBtnBg.color = 0x3a9cff; // blue overlay
closeBtnBg.interactive = true;
closeBtnBg.defaultAlpha = closeBtnBg.alpha;
closeBtnBg.down = function () {
return function (x, y, obj) {
// Visual feedback: animate alpha
closeBtnBg.alpha = 0.65;
tween(closeBtnBg, {
alpha: closeBtnBg.defaultAlpha
}, {
duration: 120
});
if (modalContainer && modalContainer.parent) modalContainer.destroy();
// Modal kapatıldığında ana menüyü tekrar göster
if (startMenuContainer && !startMenuContainer.parent) {
startMenuContainer.visible = true;
game.addChild(startMenuContainer);
}
};
}();
modalContainer.addChild(closeBtnBg);
// Dynamic hover/press highlight (top highlight)
var closeBtnHighlight = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: closeBtnY - closeBtnH * 0.22,
width: closeBtnW * 0.92,
height: closeBtnH * 0.38
});
closeBtnHighlight.alpha = 0.18;
closeBtnHighlight.color = 0xffffff;
modalContainer.addChild(closeBtnHighlight);
var closeBtnText = new Text2("Kapat", {
size: 70,
fill: "#fff",
font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'"
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtnText.x = modalW / 2;
closeBtnText.y = closeBtnY;
closeBtnText.interactive = true;
closeBtnText.down = function (bgRef) {
return function (x, y, obj) {
if (bgRef && bgRef.down) bgRef.down(x, y, obj);
};
}(closeBtnBg);
modalContainer.addChild(closeBtnText);
// Kapat butonu artık ana menüye döndürür
closeBtnBg.down = function () {
return function (x, y, obj) {
if (modalContainer && modalContainer.parent) modalContainer.destroy();
// Modal kapatıldığında ana menüyü tekrar göster
if (startMenuContainer) {
startMenuContainer.visible = true;
if (!startMenuContainer.parent) {
game.addChild(startMenuContainer);
}
}
};
}();
// Ortala ve ekrana ekle
modalContainer.x = 2048 / 2 - modalW / 2;
modalContainer.y = 2732 / 2 - modalH / 2;
game.addChild(modalContainer);
}
};
}(btnBg);
btnBgList.push(btnBg);
startMenuContainer.addChild(btnBg);
// Butonun üstüne hafif bir parlaklık efekti (degrade gibi)
var btnHighlight = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: btnY - buttonHeight / 3,
width: buttonWidth * 0.92,
height: buttonHeight * 0.38
});
btnHighlight.alpha = 0.18;
btnHighlight.color = 0xffffff;
startMenuContainer.addChild(btnHighlight);
var btnText = new Text2(menuButtons[i].label, {
size: 100,
fill: "#fff",
maxWidth: buttonWidth - 60 // buton kenarından taşmasın
});
btnText.anchor.set(0.5, 0.5);
btnText.x = menuWidth / 2;
btnText.y = btnY;
btnText.menuKey = menuButtons[i].key;
btnText.buttonIndex = i;
btnText.interactive = true;
btnText.defaultAlpha = 1;
btnText.down = function (btnBgRef, btnTextRef) {
return function (x, y, obj) {
// Text label dokunulduğunda kısa bir görsel geri bildirim uygula
btnTextRef.alpha = 0.65;
tween(btnTextRef, {
alpha: btnTextRef.defaultAlpha
}, {
duration: 120
});
// Sadece kendi butonunun down fonksiyonunu tetikle
if (btnBgRef && btnBgRef.down) {
btnBgRef.down(x, y, obj);
}
};
}(btnBg, btnText);
btnTextList.push(btnText);
startMenuContainer.addChild(btnText);
}
// Bilgilendirici kısa açıklama
var infoText = new Text2("Gemiyi sürükle, mermilerle uzay cisimlerini vur!", {
size: 70,
fill: "#fff",
maxWidth: menuWidth - 80 // kutu kenarından taşmasın
});
infoText.anchor.set(0.5, 0.5);
infoText.x = menuWidth / 2;
// Kırmızı bölümün altına hizala: kırmızı bölümün altı = startMenuBg.y + startMenuBg.height/2
infoText.y = startMenuBg.y + startMenuBg.height / 2 + 48;
startMenuContainer.addChild(infoText);
// Alt kısımda küçük bir imza
var copyrightText = new Text2("© 2024 FRVR.Ava.Combo[POGAAS]", {
size: 38,
fill: 0xB0E0FF
});
copyrightText.anchor.set(0.5, 0.5);
copyrightText.x = menuWidth / 2;
copyrightText.y = menuHeight - 32;
startMenuContainer.addChild(copyrightText);
// Ortala ve ekrana ekle
startMenuContainer.x = 2048 / 2 - menuWidth / 2;
startMenuContainer.y = 2732 / 2 - menuHeight / 2;
// Oyun başında menü ekrana eklenmez, intro bitince eklenir
// game.addChild(startMenuContainer);
// Oyun başlamadan tüm kontrolleri ve update'i devre dışı bırak
var gameStarted = false;
// Ava: Dinamik duraklatma menüsü (Devam et, Yeniden başlat, Menü)
var pauseMenuContainer = null;
function showPauseMenu() {
// Pause menu should not be shown in the main menu
if (!gameStarted) return;
if (pauseMenuContainer && pauseMenuContainer.parent) return;
if (pauseMenuContainer) pauseMenuContainer.destroy();
var pauseMenuW = 800;
var pauseMenuH = 700;
pauseMenuContainer = new Container();
var pauseBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: pauseMenuW / 2,
y: pauseMenuH / 2,
width: pauseMenuW,
height: pauseMenuH
});
pauseBg.alpha = 0.0; // Tamamen şeffaf yap
pauseBg.color = 0x181c2b;
pauseMenuContainer.addChild(pauseBg);
var pauseTitle = new Text2("Oyun Duraklatıldı", {
size: 110,
fill: 0xFFE066
});
pauseTitle.anchor.set(0.5, 0.5);
pauseTitle.x = pauseMenuW / 2;
pauseTitle.y = 140;
pauseMenuContainer.addChild(pauseTitle);
// Yeni seçenek menüsü: Oyun duraklatıldığında ekrana gelsin
var optionsMenuButtons = [{
label: "Devam et",
key: "resume",
color: 0x3a9cff
}, {
label: "Yeniden başlat",
key: "restart",
color: 0x7cbb37
}, {
label: "Menü",
key: "menu",
color: 0xf7b32b
}, {
label: "Ses Ayarları",
key: "sound",
color: 0x4e5d94
}, {
label: "Yardım",
key: "help",
color: 0x9b59b6
}];
var pBtnH = 110;
var pBtnW = 420;
var pBtnSpacing = 28;
var pFirstBtnY = 260;
for (var i = 0; i < optionsMenuButtons.length; i++) {
var pBtnY = pFirstBtnY + i * (pBtnH + pBtnSpacing);
var pBtnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: pauseMenuW / 2,
y: pBtnY,
width: pBtnW,
height: pBtnH
});
pBtnBg.alpha = 0.85;
pBtnBg.color = optionsMenuButtons[i].color;
pBtnBg.pauseKey = optionsMenuButtons[i].key;
pBtnBg.defaultAlpha = pBtnBg.alpha;
pBtnBg.interactive = true;
pBtnBg.down = function (btn) {
return function (x, y, obj) {
btn.alpha = 0.65;
tween(btn, {
alpha: btn.defaultAlpha
}, {
duration: 120
});
if (btn.pauseKey === "resume") {
// Devam et: menüyü kapat, oyuna devam et
if (pauseMenuContainer && pauseMenuContainer.parent) pauseMenuContainer.destroy();
gameStarted = true;
} else if (btn.pauseKey === "restart") {
// Yeniden başlat: oyunu baştan başlat
LK.restartGame();
} else if (btn.pauseKey === "menu") {
// Menü: ana menüyü göster, pause menüsünü kapat
if (pauseMenuContainer && pauseMenuContainer.parent) pauseMenuContainer.destroy();
showMenu();
} else if (btn.pauseKey === "sound") {
// Ses ayarları: yeni bir modal aç
var modalW = 700;
var modalH = 400;
var modalContainer = new Container();
var modalBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: modalH / 2,
width: modalW,
height: modalH
});
modalBg.alpha = 0.0; // Tamamen şeffaf yap
modalBg.color = 0x181c2b;
modalContainer.addChild(modalBg);
var modalTitle = new Text2("Ses Ayarları", {
size: 80,
fill: 0xFFE066,
maxWidth: modalW - 60
});
modalTitle.anchor.set(0.5, 0.5);
modalTitle.x = modalW / 2;
modalTitle.y = 80;
modalContainer.addChild(modalTitle);
var modalContent = new Text2("Ses ayarları burada olacak.", {
size: 50,
fill: "#fff",
maxWidth: modalW - 60
});
modalContent.anchor.set(0.5, 0);
modalContent.x = modalW / 2;
modalContent.y = 160;
modalContainer.addChild(modalContent);
// Kapat butonu
var closeBtnW = 220;
var closeBtnH = 80;
var closeBtnY = modalH - 80;
var closeBtnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: closeBtnY,
width: closeBtnW,
height: closeBtnH
});
closeBtnBg.alpha = 0.85;
closeBtnBg.color = 0x3a9cff;
closeBtnBg.interactive = true;
closeBtnBg.down = function () {
return function (x, y, obj) {
if (modalContainer && modalContainer.parent) modalContainer.destroy();
};
}();
modalContainer.addChild(closeBtnBg);
var closeBtnText = new Text2("Kapat", {
size: 60,
fill: "#fff",
font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'" // Modern font stack
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtnText.x = modalW / 2;
closeBtnText.y = closeBtnY;
closeBtnText.interactive = true;
closeBtnText.down = function (bgRef) {
return function (x, y, obj) {
if (bgRef && bgRef.down) bgRef.down(x, y, obj);
};
}(closeBtnBg);
modalContainer.addChild(closeBtnText);
// Ortala ve ekrana ekle
modalContainer.x = 2048 / 2 - modalW / 2;
modalContainer.y = 2732 / 2 - modalH / 2;
game.addChild(modalContainer);
} else if (btn.pauseKey === "help") {
// Yardım: yeni bir modal aç
var modalW = 700;
var modalH = 400;
var modalContainer = new Container();
var modalBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: modalH / 2,
width: modalW,
height: modalH
});
modalBg.alpha = 0.0; // Tamamen şeffaf yap
modalBg.color = 0x181c2b;
modalContainer.addChild(modalBg);
var modalTitle = new Text2("Yardım", {
size: 80,
fill: 0xFFE066,
maxWidth: modalW - 60
});
modalTitle.anchor.set(0.5, 0.5);
modalTitle.x = modalW / 2;
modalTitle.y = 80;
modalContainer.addChild(modalTitle);
var modalContent = new Text2("Gemiyi sürükle, mermilerle uzay cisimlerini vur!", {
size: 50,
fill: "#fff",
maxWidth: modalW - 60
});
modalContent.anchor.set(0.5, 0);
modalContent.x = modalW / 2;
modalContent.y = 160;
modalContainer.addChild(modalContent);
// Kapat butonu
var closeBtnW = 220;
var closeBtnH = 80;
var closeBtnY = modalH - 80;
var closeBtnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: closeBtnY,
width: closeBtnW,
height: closeBtnH
});
closeBtnBg.alpha = 0.85;
closeBtnBg.color = 0x3a9cff;
closeBtnBg.interactive = true;
closeBtnBg.down = function () {
return function (x, y, obj) {
if (modalContainer && modalContainer.parent) modalContainer.destroy();
};
}();
modalContainer.addChild(closeBtnBg);
var closeBtnText = new Text2("Kapat", {
size: 60,
fill: "#fff",
font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'" // Modern font stack
});
closeBtnText.anchor.set(0.5, 0.5);
closeBtnText.x = modalW / 2;
closeBtnText.y = closeBtnY;
closeBtnText.interactive = true;
closeBtnText.down = function (bgRef) {
return function (x, y, obj) {
if (bgRef && bgRef.down) bgRef.down(x, y, obj);
};
}(closeBtnBg);
modalContainer.addChild(closeBtnText);
// Ortala ve ekrana ekle
modalContainer.x = 2048 / 2 - modalW / 2;
modalContainer.y = 2732 / 2 - modalH / 2;
game.addChild(modalContainer);
}
};
}(pBtnBg);
pauseMenuContainer.addChild(pBtnBg);
var pBtnText = new Text2(optionsMenuButtons[i].label, {
size: 80,
fill: "#fff",
maxWidth: pBtnW - 40 // buton kenarından taşmasın
});
pBtnText.anchor.set(0.5, 0.5);
pBtnText.x = pauseMenuW / 2;
pBtnText.y = pBtnY;
pBtnText.interactive = true;
pBtnText.defaultAlpha = 1;
pBtnText.down = function (btnBgRef, btnTextRef) {
return function (x, y, obj) {
btnTextRef.alpha = 0.65;
tween(btnTextRef, {
alpha: btnTextRef.defaultAlpha
}, {
duration: 120
});
if (btnBgRef && btnBgRef.down) btnBgRef.down(x, y, obj);
};
}(pBtnBg, pBtnText);
pauseMenuContainer.addChild(pBtnText);
}
// Ortala ve ekrana ekle
pauseMenuContainer.x = 2048 / 2 - pauseMenuW / 2;
pauseMenuContainer.y = 2732 / 2 - pauseMenuH / 2;
game.addChild(pauseMenuContainer);
gameStarted = false;
}
// Ava: Menü oyun durduğunda tekrar gösterilsin
function showMenu() {
if (!startMenuContainer.parent) {
startMenuContainer.alpha = 1;
startMenuContainer.scaleX = 1;
startMenuContainer.scaleY = 1;
game.addChild(startMenuContainer);
}
// Oyun yeniden başlatıldığında süreyi 3 dakikaya (180 saniye) sıfırla
timeLeft = gameDuration;
updateTimerDisplay();
gameStarted = false;
// Boss diamond resetle
if (typeof bossDiamondObj !== "undefined" && bossDiamondObj) {
bossDiamondObj.destroy();
bossDiamondObj = null;
}
if (typeof game.bossDiamondSpawned !== "undefined") {
game.bossDiamondSpawned = false;
}
}
// Ava: Oyun durdurulduğunda dinamik pause menüsünü göster
game.onPause = function () {
showPauseMenu();
};
// Ava: Oyun başlatıldığında menüyü gizle (mevcut animasyonlu kod korunuyor)
// (Yukarıdaki "start" butonunun down fonksiyonu zaten menüyü yok ediyor ve gameStarted=true yapıyor.)
// Sağlık, skor ve zaman göstergeleri her zaman görünür (oyun başlamadan önce de)
// Bu kod bloğu kaldırıldı, göstergeler her zaman görünür olacak
// Her butonun kendi down fonksiyonu var, menü container'ı routing yapmaz.
// Tüm ekrana tıklama ile başlatma özelliği kaldırıldı, sadece butonlar bağımsız çalışır.
// Power-up türleri ve süreleri
var powerUpTypes = [{
type: "rapidfire",
label: "Ateş Hızı",
color: 0x3a9cff,
duration: 600
},
// 10 sn
{
type: "shield",
label: "Kalkan",
color: 0x7cbb37,
duration: 480
},
// 8 sn
{
type: "scorex2",
label: "2x Skor",
color: 0xf7b32b,
duration: 600
},
// 10 sn
{
type: "speedup",
label: "Hız",
color: 0xd729b6,
duration: 480
} // 8 sn
];
var activePowerUp = null;
var powerUpEndTick = 0;
var powerUpIcon = null;
var giftBg = null;
var giftSpawnCooldown = 900; // gift nadiren spawn olsun (900 tick ~15 saniye)
var lastGiftSpawnTick = -10000; // ilk başta hemen spawn olmasın
function spawnGift() {
if (giftBg) return; // gift zaten varsa tekrar oluşturma
// 3 farklı gift: shield, health, bulletspeed
var powerUpOptions = [{
type: "shield",
// Kalkan
label: "Kalkan",
color: 0x7cbb37,
assetId: "gift" // Kalkan için gift görseli
}, {
type: "health",
// Can
label: "Can",
color: 0xf75b5b,
assetId: "healthgift"
}, {
type: "bulletspeed",
// Mermi hızlandırma
label: "Mermi Hızı",
color: 0x3a9cff,
assetId: "mermispeedgift"
}];
// Rastgele birini seç
var pType = powerUpOptions[Math.floor(Math.random() * powerUpOptions.length)];
var assetId = pType.assetId;
giftBg = LK.getAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 600,
y: 2732 / 2 - 400,
width: 120,
height: 120
});
giftBg.alpha = 0.95;
giftBg.powerUpType = pType.type;
giftBg.powerUpColor = pType.color;
giftBg.interactive = true;
// Hareket için rastgele hızlar belirle
giftBg.vx = -4 - Math.random() * 3; // sola doğru hareket
giftBg.vy = (Math.random() - 0.5) * 2.5; // hafif yukarı/aşağı
// Parlaklık efekti
tween(giftBg, {
alpha: 0.7
}, {
duration: 400,
yoyo: true,
repeat: 9999
});
// Dokunma/çarpışma ile alınabilir ve hareketli
giftBg.update = function () {
// Hareket
giftBg.x += giftBg.vx;
giftBg.y += giftBg.vy;
// Ekran dışına çıkarsa yok et
if (giftBg.x < -150 || giftBg.x > 2048 + 150 || giftBg.y < -150 || giftBg.y > 2732 + 150) {
giftBg.destroy();
giftBg = null;
return;
}
// Oyuncu ile çarpışma
if (playerShip && isCircleHit(giftBg, playerShip)) {
// Elmas artık gift ile değil, sadece çok nadir çıkan özel bir diamond objesiyle kazanılır
// Gift yakalandığında elmas verilmez, sadece power-up veya can verir
if (giftBg.powerUpType === "health") {
// Can hediyesi: canı artır
var healAmount = 2; // Artık can hediyesi 2 can veriyor
setPlayerHealth(playerHealth + healAmount);
} else if (giftBg.powerUpType === "shield") {
// Kalkan power-up'ı uygula
activatePowerUp("shield");
} else if (giftBg.powerUpType === "bulletspeed") {
// Mermi hızlandırma power-up'ı uygula
activatePowerUp("bulletspeed");
}
// Efekt: patlama
var effect = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: giftBg.x,
y: giftBg.y,
width: 120,
height: 120
});
effect.alpha = 0.7;
game.addChild(effect);
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
effect.destroy();
}
});
giftBg.destroy();
giftBg = null;
}
// --- Nadiren çıkan diamond objesiyle elmas kazanma sistemi ---
// Diamond objesi varsa ve oyuncu ile çarpıştıysa elmas VERİLMEZ, sadece bossDiamondObj ile verilir
if (diamondObj && playerShip && isCircleHit(diamondObj, playerShip)) {
// Sadece efekt göster, elmas sayacına ekleme
var effect = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: diamondObj.x,
y: diamondObj.y,
width: 120,
height: 120
});
effect.alpha = 0.7;
game.addChild(effect);
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
effect.destroy();
}
});
diamondObj.destroy();
diamondObj = null;
}
};
game.addChild(giftBg);
lastGiftSpawnTick = LK.ticks;
}
function activatePowerUp(type) {
// Önceki power-up'ı sıfırla
if (activePowerUp && powerUpIcon) {
powerUpIcon.destroy();
powerUpIcon = null;
}
activePowerUp = type;
var pType = powerUpTypes.filter(function (p) {
return p.type === type;
})[0];
powerUpEndTick = LK.ticks + (pType ? pType.duration : 600);
// Power-up ikonunu ekle
powerUpIcon = LK.getAsset('can', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 100,
width: 120,
height: 120
});
powerUpIcon.alpha = 0.92;
powerUpIcon.color = pType ? pType.color : 0xffffff;
LK.gui.topLeft.addChild(powerUpIcon);
// Üzerine metin
var txt = new Text2(pType ? pType.label : "Power", {
size: 38,
fill: "#fff"
});
txt.anchor.set(0.5, 0.5);
txt.x = 60;
txt.y = 60;
powerUpIcon.addChild(txt);
// Efekt: kısa parlama
tween(powerUpIcon, {
alpha: 1
}, {
duration: 120,
yoyo: true,
repeat: 1
});
// Power-up efektini uygula
if (type === "rapidfire") {
shootInterval = 80; // Süper hızlı ateş
} else if (type === "shield") {
// Kalkan: bir sonraki hasarı engelle
playerShip._shielded = true;
// Görsel: geminin etrafında halka
if (!playerShip._shieldCircle) {
// Shield asset boyutunu playership'in etrafını tam sarmalayacak şekilde ayarla
// PlayerShip'in en büyük boyutunu baz al (ellipse ise genişlik/yükseklik farklı olabilir)
var maxDim = Math.max(playerShip.width, playerShip.height);
var shieldMargin = 18; // Gemi ile kalkan arasında küçük bir boşluk bırak
var shield = LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
width: maxDim + shieldMargin * 2,
height: maxDim + shieldMargin * 2
});
// Shield'ı tam olarak playership'in merkezine ortala
shield.x = 0;
shield.y = 0;
shield.alpha = 0.7;
// Kalkanı tam olarak geminin merkezine hizala (anchor 0.5,0.5 ile tam ortalanır)
playerShip.addChild(shield);
playerShip._shieldCircle = shield;
}
} else if (type === "scorex2") {
// Skor çarpanı
game._scoreMultiplier = 2;
} else if (type === "speedup") {
// Geminin hızı artsın (daha hızlı sürüklenebilsin)
playerShip._speedUp = true;
} else if (type === "bulletspeed") {
// Mermi hızı power-up: yeni mermiler daha hızlı gitsin
game._bulletSpeedUp = true;
// Ateş sıklığını da artır (daha hızlı ateş et)
shootInterval = 120; // Normalde 250, burada daha hızlı (daha düşük değer = daha sık ateş)
// Aktifken yeni mermiler hızlı olacak, Bullet sınıfı zaten bu flag'i kontrol ediyor
game._multiBullet = 3; // 3 mermi birden ateşle
}
}
function deactivatePowerUp() {
if (!activePowerUp) return;
// Efektleri sıfırla
if (activePowerUp === "rapidfire") {
shootInterval = 250;
} else if (activePowerUp === "shield") {
playerShip._shielded = false;
if (playerShip._shieldCircle) {
playerShip._shieldCircle.destroy();
playerShip._shieldCircle = null;
}
// Kalkan kaybolduğunda üstteki kalkan yazısı da kaybolsun
if (powerUpIcon) {
powerUpIcon.destroy();
powerUpIcon = null;
}
} else if (activePowerUp === "scorex2") {
game._scoreMultiplier = 1;
} else if (activePowerUp === "speedup") {
playerShip._speedUp = false;
} else if (activePowerUp === "bulletspeed") {
game._bulletSpeedUp = false;
// Artık yeni mermiler normal hızda olacak
shootInterval = 250; // Ateş sıklığını normale döndür
game._multiBullet = 1; // Tek mermiye dön
}
if (activePowerUp !== "shield" && powerUpIcon) {
powerUpIcon.destroy();
powerUpIcon = null;
}
activePowerUp = null;
powerUpEndTick = 0;
}
// Oyun değişkenleri
var playerShip = new PlayerShip();
// Oyuncu gemisi sol alt köşeden sağa hareket edecek şekilde konumlandırılır
playerShip.x = 350;
playerShip.y = 2732 / 2;
game.addChild(playerShip);
// Oyuncu gemisinin maksimum ve başlangıç sağlığı oyuna uygun şekilde ayarlandı
var playerMaxHealth = 10; // Başlangıçta 10 can
var playerHealth = playerMaxHealth;
// Sağlık değerini güvenli şekilde ayarlayan fonksiyon
function setPlayerHealth(newHealth) {
playerHealth = Math.max(0, Math.min(playerMaxHealth, newHealth));
updateCanBar();
updatePlayershipCanBar();
}
var bullets = [];
var spaceObjects = [];
var canShoot = true;
var shootInterval = 250; // ms
var lastShootTick = 0;
game._multiBullet = 1; // Başlangıçta tek mermi
var score = 0;
var difficulty = 1;
var spawnInterval = 120; // ticks, kolay başlasın
var lastSpawnTick = 0;
shootInterval = 320; // kolay başlasın, updateDifficulty ile güncellenecek
// Bölüm bitişi için toplam düşman sayacı ve kontrol değişkeni
var totalEnemiesSpawned = 0;
var levelFinished = false;
// --- High Scores (Top 5) ---
var highScores = storage.highScores && Array.isArray(storage.highScores) ? storage.highScores.slice() : [];
function saveHighScores() {
storage.highScores = highScores.slice(0, 5);
}
function addHighScore(newScore) {
highScores.push(newScore);
highScores.sort(function (a, b) {
return b - a;
});
if (highScores.length > 5) highScores.length = 5;
saveHighScores();
}
function getHighScores() {
return highScores.slice(0, 5);
}
// --- PLAYERSHIP CAN BAR (HEALTH BAR) ---
// Health bar dimensions
// Sağlık barı genişliği ve yüksekliği yeni maksimum sağlığa uygun şekilde ayarlandı
var playershipCanBarWidth = 320; // Daha kısa bar, 6 can için uygun
var playershipCanBarHeight = 38;
// Background bar
var playershipCanBarBg = new Container();
var playershipCanBarBgRect = playershipCanBarBg.attachAsset('can', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: playershipCanBarHeight / 2,
width: playershipCanBarWidth,
height: playershipCanBarHeight
});
playershipCanBarBgRect.alpha = 0.25;
// Foreground bar
var playershipCanBarFg = new Container();
var playershipCanBarFgRect = playershipCanBarFg.attachAsset('can', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: playershipCanBarHeight / 2,
width: playershipCanBarWidth,
height: playershipCanBarHeight
});
playershipCanBarFgRect.alpha = 1;
// Health bar container for positioning
var playershipCanBarContainer = new Container();
playershipCanBarContainer.addChild(playershipCanBarBg);
playershipCanBarContainer.addChild(playershipCanBarFg);
// Position: top left, but not overlapping menu (leave 100px left and top margin)
playershipCanBarContainer.x = 20;
playershipCanBarContainer.y = 20; // Move to top left, just below top margin
LK.gui.topLeft.addChild(playershipCanBarContainer);
playershipCanBarContainer.visible = true; // Her zaman görünür
// Animate health bar width and color
function updatePlayershipCanBar() {
// Yeni maksimum sağlığa göre oran
var targetWidth = playershipCanBarWidth * Math.max(0, playerHealth) / playerMaxHealth;
// Animate width using tween
tween(playershipCanBarFgRect, {
width: targetWidth
}, {
duration: 300
});
// Calculate color: green (full) to red (empty)
// 0x00FF00 (green) to 0xFF0000 (red)
var healthRatio = Math.max(0, Math.min(1, playerHealth / playerMaxHealth));
var r = Math.round(0xFF * (1 - healthRatio));
var g = Math.round(0xFF * healthRatio);
var b = 0;
var color = r << 16 | g << 8 | b;
// Animate color using tween
tween(playershipCanBarFgRect, {
color: color
}, {
duration: 300
});
}
updatePlayershipCanBar();
updateDifficulty(); // Oyun başında kolay zorluk ayarı uygula
// --- Only one health bar is visible (playershipCanBar) ---
// Animate health bar width and color
function updateCanBar() {
// Forward to playershipCanBar update for compatibility
updatePlayershipCanBar();
}
updateCanBar();
// Skor gösterimi
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
// --- Elmas sayacı ---
// Elmas sayısı için global değişken
var diamondCount = 0;
// Elmas simgesi ve sayaç için container
var diamondCounterContainer = new Container();
// Elmas simgesi (diamond asset'i ile)
var diamondIcon = LK.getAsset('diamond', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 60,
width: 80,
height: 80
});
diamondIcon.alpha = 0.95;
diamondCounterContainer.addChild(diamondIcon);
// Elmas sayısı metni
var diamondTxt = new Text2('0', {
size: 60,
fill: "#fff"
});
diamondTxt.anchor.set(0, 0.5);
diamondTxt.x = diamondIcon.x + diamondIcon.width + 18;
diamondTxt.y = 60;
diamondCounterContainer.addChild(diamondTxt);
// Elmas sayacını güncelleyen fonksiyon
function updateDiamondCounter() {
diamondTxt.setText(diamondCount + "");
}
updateDiamondCounter();
// Skor ve elmas sayaçlarını yan yana göstermek için ortak bir container oluştur
var scoreDiamondContainer = new Container();
scoreDiamondContainer.addChild(scoreTxt);
// Elmas sayacını skorun sağına hizala
diamondCounterContainer.x = scoreTxt.width / 2 + 32; // skorun sağında 32px boşluk
diamondCounterContainer.y = 0;
scoreDiamondContainer.addChild(diamondCounterContainer);
// Ortak container'ı GUI'de üstte ortala
scoreDiamondContainer.x = 0;
scoreDiamondContainer.y = 0;
LK.gui.top.addChild(scoreDiamondContainer);
scoreTxt.visible = true; // Her zaman görünür
// Süre göstergesi (3 dakika = 180 saniye)
var gameDuration = 180; // saniye
var timeLeft = gameDuration;
var timerTxt = new Text2('03:00', {
size: 100,
fill: "#fff"
});
timerTxt.anchor.set(1, 0); // Anchor right edge
LK.gui.topRight.addChild(timerTxt); // Add to right side of GUI
timerTxt.visible = true; // Her zaman görünür
// Timer'ı güncelleyen fonksiyon
function updateTimerDisplay() {
var min = Math.floor(timeLeft / 60);
var sec = Math.floor(timeLeft % 60);
var minStr = min < 10 ? "0" + min : "" + min;
var secStr = sec < 10 ? "0" + sec : "" + sec;
timerTxt.setText(minStr + ":" + secStr);
}
updateTimerDisplay();
// Her saniye zaman azaltıcı timer
var timerInterval = LK.setInterval(function () {
if (!gameStarted) return;
if (levelFinished) return;
if (timeLeft > 0) {
timeLeft -= 1;
if (timeLeft < 0) timeLeft = 0;
updateTimerDisplay();
// Zaman bittiğinde oyunu otomatik olarak yeniden başlat
if (timeLeft === 0) {
LK.restartGame();
}
}
}, 1000);
// Animate health bar width and color
updateCanBar();
// Dokunma/sürükleme ile gemi hareketi
var dragging = false;
function handleMove(x, y, obj) {
if (!gameStarted) return;
if (dragging) {
// Portal büyüme animasyonu sırasında oyuncu hareket etmesin, ancak büyüme bittiyse tekrar izin ver
var portalGrowing = false;
if (game.portal && !game.portal.isShrinking) {
// Portal büyüme animasyonu devam ediyor mu?
// 1.2'den 3.0'a büyüme: scaleX < 3.0 ise büyüme devam ediyor
if (typeof game.portal._growTweenStarted !== "undefined" && game.portal._growTweenStarted && game.portal.scaleX < 3.0 - 0.01) {
portalGrowing = true;
}
}
if (portalGrowing) {
return;
}
// Sınırları aşmasın - boss sonrası üst/alt bar varsa daraltılmış alanda hareket
var minX = playerShip.width / 2 + 40;
var maxX = 2048 - playerShip.width / 2 - 40;
var minY, maxY;
if (game._screenNarrowed && typeof game._playAreaTop !== "undefined" && typeof game._playAreaBottom !== "undefined") {
minY = game._playAreaTop + playerShip.height / 2 + 20;
maxY = game._playAreaBottom - playerShip.height / 2 - 20;
} else {
minY = playerShip.height / 2 + 40;
maxY = 2732 - playerShip.height / 2 - 40;
}
// Sadece sürükleme sırasında, gemi mouse/touch ile birlikte hareket eder
if (activePowerUp === "speedup") {
// Hız power-up'ı: gemi daha hızlı hareket etsin (pozisyona yaklaşma)
playerShip.x += (Math.max(minX, Math.min(maxX, x)) - playerShip.x) * 0.45;
playerShip.y += (Math.max(minY, Math.min(maxY, y)) - playerShip.y) * 0.45;
} else {
playerShip.x = Math.max(minX, Math.min(maxX, x));
playerShip.y = Math.max(minY, Math.min(maxY, y));
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Sadece geminin üstüne tıklanırsa sürükleme başlasın
if (!gameStarted) return;
var dx = x - playerShip.x;
var dy = y - playerShip.y;
var r = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70);
// Portal büyüme animasyonu devam ediyorsa sürükleme başlatılamasın
var portalGrowing = false;
if (game.portal && !game.portal.isShrinking) {
if (!game.portal._growTweenStarted || game.portal.scaleX < 1.8 - 0.01) {
portalGrowing = true;
}
}
if (portalGrowing) {
dragging = false;
return;
}
if (dx * dx + dy * dy <= r * r) {
dragging = true;
handleMove(x, y, obj);
} else {
dragging = false;
}
};
game.up = function (x, y, obj) {
if (!gameStarted) return;
dragging = false;
};
// Otomatik ateş (her shootInterval ms'de bir)
function tryShoot() {
if (!canShoot) return;
var multi = typeof game._multiBullet !== "undefined" ? game._multiBullet : 1;
var spread = 38; // mermiler arası dikey mesafe
for (var i = 0; i < multi; i++) {
var bullet = new Bullet();
bullet.x = playerShip.x + playerShip.width / 2 + 10;
// Ortadaki mermi tam ortada, diğerleri yukarı ve aşağıya kaydırılır
bullet.y = playerShip.y + (i - (multi - 1) / 2) * spread;
bullets.push(bullet);
game.addChild(bullet);
}
canShoot = false;
LK.setTimeout(function () {
canShoot = true;
}, shootInterval);
}
// Uzay cismi oluştur
function spawnSpaceObject() {
// 0: uzayNesnesi2 (enemy), 1: spaceObject (asteroid), 2: meteorstone (yeni düşman)
// Düşman gemilerinin sıklığını artırmak için oranı yükselttik
var rand = Math.random();
var obj;
// enemyship2 sadece zorluk 4 ve üstünde görünsün
if (rand < 0.6 && difficulty >= 4) {
// Only allow one enemyship2 on screen at a time
var hasEnemyship2 = false;
for (var i = 0; i < spaceObjects.length; i++) {
var so = spaceObjects[i];
if (so.attachAsset && so.attachAsset('enemyship2', {
anchorX: 0.5,
anchorY: 0.5
})) {
hasEnemyship2 = true;
break;
}
}
if (hasEnemyship2) {
// Do not spawn another enemyship2
return;
}
// enemyship2 (yeni düşman tipi)
obj = new Container();
obj.health = 20; // enemyship2 canı 20 olarak başlatıldı
var width = 300;
var height = 300;
var objAsset = obj.attachAsset('enemyship2', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
objAsset.color = 0xff4444;
obj.radius = width / 2;
obj.x = 2048 + width;
obj.y = 200 + Math.random() * (2732 - 400);
// Düşman hızı: kolayda yavaş, zorda hızlı
var baseSpeed = 4 + (difficulty - 4) * 0.8;
var speed = baseSpeed + Math.random() * (2.0 + difficulty * 0.3);
obj.vx = -speed;
obj.vy = (Math.random() - 0.5) * (3.5 + difficulty * 0.3);
// --- EN AZ 10 SANİYE EKRANDA KALMA ---
// enemyship2 ekranda kalma süresi (tick cinsinden)
obj._minScreenTicks = 600; // 10 saniye (60fps)
// enemyship2'nin ekranda kalmaya başladığı tick
obj._spawnTick = LK.ticks;
// enemyship2 yok edilebilir mi? (başta false, 10sn sonra true)
obj._canBeDestroyed = false;
// --- RANDOM SALDIRI MEKANİĞİ ---
// Rastgele saldırı için bir sonraki saldırı tick'i
obj._nextRandomAttackTick = LK.ticks + 60 + Math.floor(Math.random() * 120); // 1-3 sn arası ilk saldırı
// Enemy bullet fire timer
obj.enemyBulletCooldown = 7 + Math.floor(Math.random() * 7); // DAHA DA SIK ateş (daha seri)
obj.lastEnemyBulletTick = LK.ticks;
// --- LAZER IŞINI: enemyship2 özel saldırısı ---
// Lazer ışını için state ve timerlar
obj.laserCooldown = 240 + Math.floor(Math.random() * 120); // 4-6 saniyede bir
obj.lastLaserTick = LK.ticks;
obj.laserActive = false;
obj.laserDuration = 60; // lazer açık kalma süresi (1 saniye)
obj.laserBeam = null;
// Lazer ateşleme etkin: enemyship2 için lazer saldırısı aktif
// --- YAPAY ZEKA: Oyuncuya yaklaşma ve akıllı ateş etme ---
obj.update = function () {
// Akıllı hareket: oyuncuya doğru yavaşça yönel
if (playerShip && typeof playerShip.x !== "undefined" && typeof playerShip.y !== "undefined") {
var dx = playerShip.x - obj.x;
var dy = playerShip.y - obj.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// X ekseninde oyuncuya yaklaşmak için vx'yi ayarla
var targetVx = -Math.max(3, Math.min(12, Math.abs(dx) / 30));
if (obj.x > playerShip.x) {
obj.vx += (targetVx - obj.vx) * 0.10;
}
// Y ekseninde oyuncuya yaklaşmak için vy'yi ayarla
var targetVy = 0;
if (dist > 1) {
targetVy = dy / Math.max(60, Math.abs(dx));
if (targetVy > 6) targetVy = 6;
if (targetVy < -6) targetVy = -6;
}
obj.vy += (targetVy - obj.vy) * 0.15;
}
obj.x += obj.vx;
obj.y += obj.vy;
// --- EKRANA GİRİNCE ATEŞ ETME BAŞLASIN ---
// Ekrana ilk kez girdiği anı tespit et
if (typeof obj._hasStartedFiring === "undefined") obj._hasStartedFiring = false;
if (!obj._hasStartedFiring && obj.x <= 2048) {
obj._hasStartedFiring = true;
// İlk ateş için timerları hemen başlat
obj.lastEnemyBulletTick = LK.ticks;
if (typeof obj._nextRandomAttackTick !== "undefined") {
obj._nextRandomAttackTick = LK.ticks + 10 + Math.floor(Math.random() * 30); // Hemen random saldırı başlat
}
if (typeof obj.laserStartTick !== "undefined") {
obj.laserStartTick = LK.ticks;
}
}
// --- EN AZ 10 SANİYE EKRANDA KALMA KONTROLÜ ---
if (!obj._canBeDestroyed && LK.ticks - obj._spawnTick >= obj._minScreenTicks) {
obj._canBeDestroyed = true;
}
// --- RANDOM SALDIRI MEKANİĞİ ---
// 10 saniye dolduysa random saldırı yapabilir
if (LK.ticks - obj._spawnTick >= obj._minScreenTicks && LK.ticks >= obj._nextRandomAttackTick) {
// Saldırı türünü rastgele seç: 0=normal mermi, 1=lazer, 2=çift mermi, 3=ani hızlanma
var attackType = Math.floor(Math.random() * 4);
if (attackType === 0) {
// Normal mermi ateşi (hedefli)
var eb = new EnemyBullet();
eb.x = obj.x - 60;
eb.y = obj.y;
if (!game.enemyBullets) game.enemyBullets = [];
game.enemyBullets.push(eb);
game.addChild(eb);
} else if (attackType === 1 && !obj.laserActive) {
// Lazer saldırısı başlat (lazer zaten aktif değilse)
obj.laserActive = true;
obj.laserStartTick = LK.ticks;
var laserLength = obj.x - 0;
var laserWidth = 38 + Math.random() * 18;
var laserY = obj.y;
obj.laserBeam = LK.getAsset('lazer', {
anchorX: 1.0,
anchorY: 0.5,
x: obj.x - width / 2 - 10,
y: laserY,
width: laserLength,
height: laserWidth
});
obj.laserBeam.alpha = 0.38 + Math.random() * 0.18;
obj.laserBeam.laserOwner = obj;
obj.laserBeam._baseY = laserY;
obj.laserBeam._baseWidth = laserWidth;
obj.laserBeam.update = function () {
if (!obj.laserActive) return;
obj.laserBeam.y = obj.y;
obj.laserBeam.width = obj.x - 0;
obj.laserBeam.height = obj.laserBeam._baseWidth + Math.sin(LK.ticks / 2) * 8;
obj.laserBeam.alpha = 0.38 + Math.abs(Math.sin(LK.ticks / 8)) * 0.22;
};
game.addChild(obj.laserBeam);
} else if (attackType === 2) {
// Çift mermi ateşi (yukarı ve aşağı)
for (var i = -1; i <= 1; i += 2) {
var eb2 = new EnemyBullet();
eb2.x = obj.x - 60;
eb2.y = obj.y + i * 60;
if (!game.enemyBullets) game.enemyBullets = [];
game.enemyBullets.push(eb2);
game.addChild(eb2);
}
} else if (attackType === 3) {
// Ani hızlanma (kısa süre için vx artır)
obj.vx -= 6 + Math.random() * 4;
}
// Bir sonraki random saldırı için tick ayarla (her seferinde 1-3 sn arası)
obj._nextRandomAttackTick = LK.ticks + 60 + Math.floor(Math.random() * 120);
}
// --- LAZER IŞINI AKTİVASYONU ---
// Lazer aktif değilse ve cooldown dolduysa lazeri başlat
if (!obj.laserActive && LK.ticks - obj.lastLaserTick > obj.laserCooldown) {
obj.laserActive = true;
obj.laserStartTick = LK.ticks;
// Lazer ışını görseli: lazer image asset'i ile (kırmızı, şeffaf)
var laserLength = obj.x - 0; // Ekranın soluna kadar
var laserWidth = 38 + Math.random() * 18; // 38-56px arası
var laserY = obj.y;
obj.laserBeam = LK.getAsset('lazer', {
anchorX: 1.0,
anchorY: 0.5,
x: obj.x - width / 2 - 10,
y: laserY,
width: laserLength,
height: laserWidth
});
obj.laserBeam.alpha = 0.38 + Math.random() * 0.18;
obj.laserBeam.laserOwner = obj;
// Hafif titreme efekti için orijinal y ve width kaydet
obj.laserBeam._baseY = laserY;
obj.laserBeam._baseWidth = laserWidth;
// Lazer update fonksiyonu: objenin y'sini takip etsin, titreme efekti
obj.laserBeam.update = function () {
if (!obj.laserActive) return;
// Lazerin y'si enemyship2'nin y'sini takip etsin
obj.laserBeam.y = obj.y;
// Lazerin uzunluğu obj.x'den ekrandaki en sol noktaya kadar
obj.laserBeam.width = obj.x - 0;
// Hafif titreme efekti
obj.laserBeam.height = obj.laserBeam._baseWidth + Math.sin(LK.ticks / 2) * 8;
obj.laserBeam.alpha = 0.38 + Math.abs(Math.sin(LK.ticks / 8)) * 0.22;
};
game.addChild(obj.laserBeam);
}
// Lazer aktifse, süresi dolduysa kapat
if (obj.laserActive) {
if (LK.ticks - obj.laserStartTick > obj.laserDuration) {
obj.laserActive = false;
obj.lastLaserTick = LK.ticks;
obj.laserCooldown = 240 + Math.floor(Math.random() * 120);
if (obj.laserBeam && obj.laserBeam.parent) {
obj.laserBeam.destroy();
}
obj.laserBeam = null;
} else if (obj.laserBeam && obj.laserBeam.update) {
obj.laserBeam.update();
// Lazer ışını ile oyuncu çarpışma kontrolü (dikdörtgen-çember)
// Lazerin dikdörtgeni: (x1, y1, x2, y2)
var lx1 = obj.laserBeam.x - obj.laserBeam.width;
var lx2 = obj.laserBeam.x;
var ly1 = obj.laserBeam.y - obj.laserBeam.height / 2;
var ly2 = obj.laserBeam.y + obj.laserBeam.height / 2;
// Oyuncu çemberi
if (playerShip) {
var px = playerShip.x;
var py = playerShip.y;
var pr = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70);
// Çember-dikdörtgen çarpışma
var closestX = Math.max(lx1, Math.min(px, lx2));
var closestY = Math.max(ly1, Math.min(py, ly2));
var dx = px - closestX;
var dy = py - closestY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < pr - 8) {
// Sadece ilk çarpışmada hasar uygula (her frame değil)
if (!obj.laserBeam._playerHit) {
obj.laserBeam._playerHit = true;
// Patlama efekti
var explosion = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width || 140,
height: playerShip.height || 100
});
game.addChild(explosion);
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Kalkan power-up aktifse ilk hasarı engelle
if (activePowerUp === "shield" && playerShip._shielded) {
playerShip._shielded = false;
if (playerShip._shieldCircle) {
tween(playerShip._shieldCircle, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
playerShip._shieldCircle.destroy();
playerShip._shieldCircle = null;
}
});
}
var shieldHit = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width * 1.7,
height: playerShip.height * 1.7
});
shieldHit.alpha = 0.5;
shieldHit.color = 0x7cbb37;
game.addChild(shieldHit);
tween(shieldHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
shieldHit.destroy();
}
});
// Hasarı engelle, can azalmasın
} else {
setPlayerHealth(playerHealth - 4); // Lazer ışını hasarı
}
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
}
} else {
obj.laserBeam._playerHit = false;
}
}
}
}
// Ateş etme (her cooldown süresi dolduğunda)
if (LK.ticks - obj.lastEnemyBulletTick > obj.enemyBulletCooldown) {
// Oyuncuya odaklı ateş: eğer oyuncu yatayda önünde ve menzildeyse ateş et, yoksa rastgele daha az ateş etsin
var shouldFire = false;
if (playerShip && obj.x > playerShip.x) {
// Düşman oyuncunun sağında olmalı
var dy = Math.abs(obj.y - playerShip.y);
// Y ekseninde yakınlık arttıkça ateş olasılığı artsın
if (dy < 80) {
shouldFire = true; // Çok yakınsa kesin ateş et
} else if (dy < 180 && Math.random() < 0.5) {
shouldFire = true; // Orta mesafede %50 olasılıkla ateş et
} else if (dy < 300 && Math.random() < 0.15) {
shouldFire = true; // Uzakta ise nadiren ateş et
}
} else if (Math.random() < 0.03) {
// Ekranda oyuncu yoksa veya çok uzaktaysa çok nadiren ateş etsin
shouldFire = true;
}
if (shouldFire) {
var eb = new EnemyBullet();
eb.x = obj.x - 60;
eb.y = obj.y;
if (!game.enemyBullets) game.enemyBullets = [];
game.enemyBullets.push(eb);
game.addChild(eb);
obj.lastEnemyBulletTick = LK.ticks;
// Oyuncuya yakınken daha kısa cooldown, uzaktayken daha uzun
if (playerShip && Math.abs(obj.y - playerShip.y) < 80) {
obj.enemyBulletCooldown = 14 + Math.floor(Math.random() * 8); // Çok yakınsa çok sık ateş
} else if (playerShip && Math.abs(obj.y - playerShip.y) < 180) {
obj.enemyBulletCooldown = 22 + Math.floor(Math.random() * 12); // Orta mesafe
} else {
obj.enemyBulletCooldown = 38 + Math.floor(Math.random() * 22); // Uzakta daha seyrek ateş
}
}
}
};
} else if (rand < 0.6) {
// uzayNesnesi2 (enemy ship) - eski düşman, sadece zorluk 4'ten önce
obj = new Container();
var width = 100;
var height = 100;
var objAsset = obj.attachAsset('uzayNesnesi2', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
objAsset.color = 0xff4444;
obj.radius = width / 2;
obj.x = 2048 + width;
obj.y = 200 + Math.random() * (2732 - 400);
// Düşman hızı: kolayda yavaş, zorda hızlı
// 1. zorlukta ~3, 10. zorlukta ~9
var baseSpeed = 3 + (difficulty - 1) * 0.7;
var speed = baseSpeed + Math.random() * (1.5 + difficulty * 0.2);
obj.vx = -speed;
obj.vy = (Math.random() - 0.5) * (2.5 + difficulty * 0.2);
// Enemy bullet fire timer
obj.enemyBulletCooldown = 10 + Math.floor(Math.random() * 10); // DAHA DA SIK ateş (daha seri)
obj.lastEnemyBulletTick = LK.ticks;
// --- YAPAY ZEKA: Oyuncuya yaklaşma ve akıllı ateş etme ---
obj.update = function () {
// Akıllı hareket: oyuncuya doğru yavaşça yönel
if (playerShip && typeof playerShip.x !== "undefined" && typeof playerShip.y !== "undefined") {
// Yalnızca ekranda ise takip et
var dx = playerShip.x - obj.x;
var dy = playerShip.y - obj.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// X ekseninde oyuncuya yaklaşmak için vx'yi ayarla (mantıklı takip)
var targetVx = -Math.max(2, Math.min(10, Math.abs(dx) / 40));
if (obj.x > playerShip.x) {
obj.vx += (targetVx - obj.vx) * 0.08;
}
// Y ekseninde oyuncuya yaklaşmak için vy'yi ayarla (smooth takip)
var targetVy = 0;
if (dist > 1) {
targetVy = dy / Math.max(80, Math.abs(dx)); // X uzaklığı arttıkça daha az dikey hareket
// Sınırla, çok hızlı olmasın
if (targetVy > 4) targetVy = 4;
if (targetVy < -4) targetVy = -4;
}
// Yavaşça vy'ye yaklaş
obj.vy += (targetVy - obj.vy) * 0.12;
}
obj.x += obj.vx;
obj.y += obj.vy;
// --- EKRANA GİRİNCE ATEŞ ETME BAŞLASIN ---
// Ekrana ilk kez girdiği anı tespit et
if (typeof obj._hasStartedFiring === "undefined") obj._hasStartedFiring = false;
if (!obj._hasStartedFiring && obj.x <= 2048) {
obj._hasStartedFiring = true;
// İlk ateş için timerı hemen başlat
obj.lastEnemyBulletTick = LK.ticks;
}
// Ateş etme (her cooldown süresi dolduğunda)
if (LK.ticks - obj.lastEnemyBulletTick > obj.enemyBulletCooldown) {
// Oyuncuya odaklı ateş: eğer oyuncu yatayda önünde ve menzildeyse ateş et, yoksa rastgele daha az ateş etsin
var shouldFire = false;
if (playerShip && obj.x > playerShip.x) {
var dy = Math.abs(obj.y - playerShip.y);
if (dy < 60) {
shouldFire = true; // Çok yakınsa kesin ateş et
} else if (dy < 140 && Math.random() < 0.5) {
shouldFire = true; // Orta mesafe %50 olasılıkla ateş et
} else if (dy < 220 && Math.random() < 0.12) {
shouldFire = true; // Uzakta ise nadiren ateş et
}
} else if (Math.random() < 0.02) {
// Ekranda oyuncu yoksa veya çok uzaktaysa çok nadiren ateş etsin
shouldFire = true;
}
if (shouldFire) {
var eb = new EnemyBullet();
eb.x = obj.x - 60;
eb.y = obj.y;
if (!game.enemyBullets) game.enemyBullets = [];
game.enemyBullets.push(eb);
game.addChild(eb);
obj.lastEnemyBulletTick = LK.ticks;
// Oyuncuya yakınken daha kısa cooldown, uzaktayken daha uzun
if (playerShip && Math.abs(obj.y - playerShip.y) < 60) {
obj.enemyBulletCooldown = 18 + Math.floor(Math.random() * 8); // Çok yakınsa çok sık ateş
} else if (playerShip && Math.abs(obj.y - playerShip.y) < 140) {
obj.enemyBulletCooldown = 28 + Math.floor(Math.random() * 10); // Orta mesafe
} else {
obj.enemyBulletCooldown = 54 + Math.floor(Math.random() * 24); // Uzakta daha seyrek ateş
}
}
}
};
} else if (rand < 0.3) {
// spaceObject (asteroid)
obj = new Container();
var width = 120 + Math.random() * 60;
var height = 120 + Math.random() * 60;
var objAsset = obj.attachAsset('spaceObject', {
anchorX: 0.5,
anchorY: 0.5
});
objAsset.width = width;
objAsset.height = height;
objAsset.color = 0x888888;
obj.radius = width / 2;
obj.x = 2048 + width;
obj.y = 200 + Math.random() * (2732 - 400);
// Asteroid hızı: kolayda yavaş, zorda hızlı
// 1. zorlukta ~2.5, 10. zorlukta ~8
var baseSpeed = 2.5 + (difficulty - 1) * 0.6;
var speed = baseSpeed + Math.random() * (1.5 + difficulty * 0.2);
obj.vx = -speed;
obj.vy = (Math.random() - 0.5) * (2 + difficulty * 0.2);
obj.update = function () {
obj.x += obj.vx;
obj.y += obj.vy;
};
} else {
// meteorstone (yeni düşman)
// MeteorStone: kolayda yavaş, zorda hızlı
obj = new MeteorStone();
if (obj && obj.vx !== undefined) {
// 1. zorlukta ~-3, 10. zorlukta ~-8
var meteorBaseSpeed = 3 + (difficulty - 1) * 0.6;
obj.vx = -meteorBaseSpeed - Math.random() * (1.5 + difficulty * 0.2);
obj.vy = (Math.random() - 0.5) * (2.5 + difficulty * 0.2);
}
}
spaceObjects.push(obj);
game.addChild(obj);
// Düşman sayısını artır ve 10'a ulaştıysa win kontrolü
totalEnemiesSpawned++;
// (Kazanan kontrolü kaldırıldı)
}
// Çarpışma kontrolü (daire-çarpışma)
function isCircleHit(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var r1 = a.radius || (a.width ? a.width / 2 : 0);
var r2 = b.radius || (b.width ? b.width / 2 : 0);
return dist < r1 + r2 - 10;
}
// Zorluk arttırma ve oyun hızını kademeli olarak artır
function updateDifficulty() {
// Zorluk: 1-10 arası, her 10 puanda bir artar, maksimum 10
var newDifficulty = 1 + Math.floor(score / 10);
if (newDifficulty > 10) newDifficulty = 10;
if (newDifficulty > difficulty) {
difficulty = newDifficulty;
}
// spawnInterval: Kolayda yavaş (120), zorda hızlı (30)
// 1. zorlukta 120, 10. zorlukta 30
spawnInterval = Math.round(120 - (difficulty - 1) * 10);
if (spawnInterval < 30) spawnInterval = 30;
// Mermi hızını ve ateş sıklığını zorlukla birlikte artır
// Kolayda yavaş, zorda hızlı
// shootInterval: 1. zorlukta 320, 10. zorlukta 120
shootInterval = Math.round(320 - (difficulty - 1) * 22);
if (shootInterval < 90) shootInterval = 90;
// Düşman mermisi hızı ve spawn oranı da zorlukla birlikte artacak şekilde ayarlanabilir
// (EnemyShip ve Asteroid spawn fonksiyonlarında da difficulty kullanılıyor)
}
// Oyun döngüsü
game.update = function () {
// (Geri alındı: ekran sağa doğru ilerlemesin, scrollX ve scrollSpeed kaldırıldı)
// Galaksi arka planı kaldırıldı
// Yıldızlar: parallax ve hafif döndürme
if (typeof starBgContainer !== "undefined" && stars && stars.length) {
for (var si = 0; si < stars.length; si++) {
var s = stars[si];
s.x -= s._vx;
s.rotation += s._rotSpeed;
// Ekrandan soldan çıkarsa sağa wrap et
if (s.x < -10) {
s.x = 2048 + 10;
s.y = Math.random() * 2732;
}
}
}
if (!gameStarted) return;
// Playership sağlık barı 0 olduğunda oyun bitsin, aksi takdirde bitmesin
if (playerHealth <= 0) {
updateCanBar();
updatePlayershipCanBar();
// --- High Score Save ---
addHighScore(score);
// Boss diamond resetle
if (typeof bossDiamondObj !== "undefined" && bossDiamondObj) {
bossDiamondObj.destroy();
bossDiamondObj = null;
}
if (typeof game.bossDiamondSpawned !== "undefined") {
game.bossDiamondSpawned = false;
}
LK.showGameOver();
return;
}
// Süreyi azalt (her frame ~1/60 saniye)
// Artık sadece timerInterval ile zaman azalacak, burada azaltma yapılmıyor
// 10 düşman spawn olduysa ve can > 0 ve süre > 0 ise win
// (Kazanan kontrolü kaldırıldı)
// Planets removed
// Otomatik ateş
// Portal büyüme veya küçülme animasyonu sırasında mermi atılmasın
var portalBlockingShoot = false;
if (game.portal && !game.portal.isShrinking && typeof game.portal.lastWasIntersecting !== "undefined" && game.portal.lastWasIntersecting) {
portalBlockingShoot = true;
}
if (!portalBlockingShoot && LK.ticks - lastShootTick > Math.floor(shootInterval / 16)) {
tryShoot();
lastShootTick = LK.ticks;
}
// Uzay cismi oluşturma
if (!levelFinished && LK.ticks - lastSpawnTick > spawnInterval) {
spawnSpaceObject();
lastSpawnTick = LK.ticks;
}
// Mermileri güncelle
if (!(game.portal && !game.portal.isShrinking && game.portal.scaleX < (typeof maxScale !== "undefined" ? maxScale : 999))) {
// Portal büyüme animasyonu sırasında mermiler yok edilir
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Ekran dışıysa sil
if (b.x > 2048 + 50) {
b.destroy();
bullets.splice(i, 1);
}
}
} else {
// Portal büyüme animasyonu sırasında tüm mermileri yok et
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
if (b && b.parent) {
tween(b, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 200,
onFinish: function (bb) {
return function () {
if (bb && bb.parent) bb.destroy();
};
}(b)
});
}
}
bullets = [];
}
// Uzay cisimlerini güncelle
for (var j = spaceObjects.length - 1; j >= 0; j--) {
var obj = spaceObjects[j];
obj.update();
// Ekran dışıysa sil
if (obj.x < -200 || obj.y < -200 || obj.y > 2732 + 200) {
obj.destroy();
spaceObjects.splice(j, 1);
continue;
}
// Gemiye çarptı mı?
if (isCircleHit(obj, playerShip)) {
// Eğer kalkan aktifse, hiçbir şey olmasın, düşman da yok olmasın
if (activePowerUp === "shield" && playerShip._shielded) {
// Kalkan varken düşman çarpışması tamamen etkisiz, hiçbir efekt, hasar veya yok etme işlemi yapılmaz
continue;
}
// Patlama efekti (patlamaeffekt görseli ile) oyuncu gemisinin üstünde göster
var explosion = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width || 140,
height: playerShip.height || 100
});
game.addChild(explosion);
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Farklı düşman türlerine göre hasar uygula
var damage = 1;
if (obj instanceof MeteorStone) {
damage = 3;
} else if (obj.attachAsset && obj.attachAsset('uzayNesnesi2', {
anchorX: 0.5,
anchorY: 0.5
})) {
// EnemyShip ise 2 birim (uzayNesnesi2)
damage = 2;
} else if (obj.attachAsset && obj.attachAsset('spaceObject', {
anchorX: 0.5,
anchorY: 0.5
})) {
// SpaceObject asteroid ise 1 birim
damage = 1;
}
setPlayerHealth(playerHealth - damage);
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
obj.destroy();
spaceObjects.splice(j, 1);
continue;
}
// Mermiyle çarpışma
var _loop = function _loop() {
b = bullets[k];
if (isCircleHit(obj, b)) {
// Patlama efekti (patlamaeffekt görseli ile)
explosion = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: obj.x,
y: obj.y,
width: obj.width || 100,
height: obj.height || 100
});
game.addChild(explosion);
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// enemyship2 ise (büyük kırmızı gemi), 2 mermi isabet edince yok olsun
if (obj.attachAsset && obj.attachAsset('enemyship2', {
anchorX: 0.5,
anchorY: 0.5
})) {
// Skor: enemyship2 için 5 puan verelim (isteğe bağlı, 3 de olabilir)
// --- Ava: 2 mermi isabet edince yok olma sistemi ---
if (typeof obj._hitCount === "undefined") obj._hitCount = 0;
obj._hitCount++;
b.destroy();
bullets.splice(k, 1);
if (obj._hitCount >= 2) {
var scoreToAdd = 5;
obj.destroy();
spaceObjects.splice(j, 1);
var multiplier = game._scoreMultiplier && game._scoreMultiplier > 1 ? game._scoreMultiplier : 1;
score += scoreToAdd * multiplier;
scoreTxt.setText(score);
updateDifficulty();
// Bölüm sonu: 10 düşman öldürüldüyse bitir
if (!levelFinished) {
if (typeof game.enemiesKilled === "undefined") game.enemiesKilled = 0;
game.enemiesKilled++;
if (game.enemiesKilled >= 50) {
levelFinished = true;
// Bölüm sonu canavarı görselini göster
if (typeof game.bossImageShown === "undefined" || !game.bossImageShown) {
var _flashBoss = function flashBoss() {
if (!game.bossImg) return;
tween(game.bossImg, {
alpha: 1
}, {
duration: 120,
onFinish: function onFinish() {
tween(game.bossImg, {
alpha: 0
}, {
duration: 120,
onFinish: function onFinish() {
flashCount++;
if (flashCount < 3) {
_flashBoss();
} else {
// Sonunda kalıcı olarak görünür olsun
tween(game.bossImg, {
alpha: 1
}, {
duration: 120
});
}
}
});
}
});
};
// Sağda, birden yanıp sönerek beliren ve aşağı yukarı hareket eden boss
bossImg = LK.getAsset('bolumsonucanavar', {
anchorX: 0.5,
anchorY: 0.5,
// Ekranın sağında, ortalanmış şekilde göster
x: 2048 - 200,
y: 2732 / 2,
width: 400,
height: 400
});
bossImg.alpha = 0;
game.addChild(bossImg);
game.bossImageShown = true;
game.bossImg = bossImg;
game.bossAppearTick = LK.ticks;
// Yanıp sönme animasyonu (3 kez)
flashCount = 0;
_flashBoss();
// Boss'un aşağı yukarı hareketi için tick kaydı
game.bossBaseY = bossImg.y;
// --- SADECE BÖLÜM SONU CANAVARI KALSIN ---
// Tüm uzay cisimlerini sil
for (var jj = spaceObjects.length - 1; jj >= 0; jj--) {
if (spaceObjects[jj]) {
spaceObjects[jj].destroy();
}
}
spaceObjects = [];
// Tüm mermileri sil
for (var ii = bullets.length - 1; ii >= 0; ii--) {
if (bullets[ii]) {
bullets[ii].destroy();
}
}
bullets = [];
// Tüm düşman mermilerini sil
if (game.enemyBullets) {
for (var eb = game.enemyBullets.length - 1; eb >= 0; eb--) {
if (game.enemyBullets[eb]) {
game.enemyBullets[eb].destroy();
}
}
game.enemyBullets = [];
}
// Gift varsa sil
if (giftBg) {
giftBg.destroy();
giftBg = null;
}
}
// Oyun bitmesin, win popup gösterme
return {
v: void 0
};
}
}
return 0; // break
}
} else {
obj.destroy();
spaceObjects.splice(j, 1);
b.destroy();
bullets.splice(k, 1);
// Skor: meteorstone=2, spaceObject=1, enemy ship=3
var scoreToAdd = 1;
// MeteorStone ise 2 puan
if (obj instanceof MeteorStone) {
scoreToAdd = 2;
}
// EnemyShip ise 3 puan
else if (obj.attachAsset && obj.attachAsset('uzayNesnesi2', {
anchorX: 0.5,
anchorY: 0.5
})) {
scoreToAdd = 3;
}
// SpaceObject asteroid ise 1 puan (default)
else if (obj.attachAsset && obj.attachAsset('spaceObject', {
anchorX: 0.5,
anchorY: 0.5
})) {
scoreToAdd = 1;
}
}
// Power-up skor çarpanı uygula
var multiplier = game._scoreMultiplier && game._scoreMultiplier > 1 ? game._scoreMultiplier : 1;
score += scoreToAdd * multiplier;
scoreTxt.setText(score);
updateDifficulty();
// Bölüm sonu: 10 düşman öldürüldüyse bitir
if (!levelFinished) {
if (typeof game.enemiesKilled === "undefined") game.enemiesKilled = 0;
game.enemiesKilled++;
if (game.enemiesKilled >= 50) {
levelFinished = true;
// Bölüm sonu canavarı görselini göster
if (typeof game.bossImageShown === "undefined" || !game.bossImageShown) {
var _flashBoss = function flashBoss() {
if (!game.bossImg) return;
tween(game.bossImg, {
alpha: 1
}, {
duration: 120,
onFinish: function onFinish() {
tween(game.bossImg, {
alpha: 0
}, {
duration: 120,
onFinish: function onFinish() {
flashCount++;
if (flashCount < 3) {
_flashBoss();
} else {
// Sonunda kalıcı olarak görünür olsun
tween(game.bossImg, {
alpha: 1
}, {
duration: 120
});
}
}
});
}
});
};
// Sağda, birden yanıp sönerek beliren ve aşağı yukarı hareket eden boss
bossImg = LK.getAsset('bolumsonucanavar', {
anchorX: 0.5,
anchorY: 0.5,
// Ekranın sağında, ortalanmış şekilde göster
x: 2048 - 200,
y: 2732 / 2,
width: 400,
height: 400
});
bossImg.alpha = 0;
game.addChild(bossImg);
game.bossImageShown = true;
game.bossImg = bossImg;
game.bossAppearTick = LK.ticks;
// Yanıp sönme animasyonu (3 kez)
flashCount = 0;
_flashBoss();
// Boss'un aşağı yukarı hareketi için tick kaydı
game.bossBaseY = bossImg.y;
// --- SADECE BÖLÜM SONU CANAVARI KALSIN ---
// Tüm uzay cisimlerini sil
for (var jj = spaceObjects.length - 1; jj >= 0; jj--) {
if (spaceObjects[jj]) {
spaceObjects[jj].destroy();
}
}
spaceObjects = [];
// Tüm mermileri sil
for (var ii = bullets.length - 1; ii >= 0; ii--) {
if (bullets[ii]) {
bullets[ii].destroy();
}
}
bullets = [];
// Tüm düşman mermilerini sil
if (game.enemyBullets) {
for (var eb = game.enemyBullets.length - 1; eb >= 0; eb--) {
if (game.enemyBullets[eb]) {
game.enemyBullets[eb].destroy();
}
}
game.enemyBullets = [];
}
// Gift varsa sil
if (giftBg) {
giftBg.destroy();
giftBg = null;
}
}
// Oyun bitmesin, win popup gösterme
return {
v: void 0
};
}
}
return 0; // break
}
},
b,
explosion,
scoreToAdd,
bossImg,
flashCount,
_ret;
for (var k = bullets.length - 1; k >= 0; k--) {
_ret = _loop();
if (_ret === 0) break;
if (_ret) return _ret.v;
}
}
// Düşman mermileri güncelle ve çarpışma kontrolü
if (game.enemyBullets) {
for (var eb = game.enemyBullets.length - 1; eb >= 0; eb--) {
var enemyBullet = game.enemyBullets[eb];
enemyBullet.update();
// Ekran dışıysa sil
if (enemyBullet.x < -100) {
enemyBullet.destroy();
game.enemyBullets.splice(eb, 1);
continue;
}
// Oyuncuya çarptı mı?
if (isCircleHit(enemyBullet, playerShip)) {
// Patlama efekti (patlamaeffekt görseli ile) oyuncu gemisinin üstünde göster
var explosion = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width || 140,
height: playerShip.height || 100
});
game.addChild(explosion);
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Kalkan power-up aktifse ilk hasarı engelle
if (activePowerUp === "shield" && playerShip._shielded) {
playerShip._shielded = false;
if (playerShip._shieldCircle) {
tween(playerShip._shieldCircle, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
playerShip._shieldCircle.destroy();
playerShip._shieldCircle = null;
}
});
}
var shieldHit = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width * 1.7,
height: playerShip.height * 1.7
});
shieldHit.alpha = 0.5;
shieldHit.color = 0x7cbb37;
game.addChild(shieldHit);
tween(shieldHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
shieldHit.destroy();
}
});
// Hasarı engelle, can azalmasın
} else {
setPlayerHealth(playerHealth - 2);
}
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
enemyBullet.destroy();
game.enemyBullets.splice(eb, 1);
continue;
}
}
}
// Boss varsa, ekranda merkeze kadar her yönde hareket ettir
if (game.bossImg && game.bossBaseY !== undefined) {
// --- BOSS MERMİSİ ATEŞLEME ---
if (typeof game.bossBulletCooldown === "undefined") {
game.bossBulletCooldown = 60 + Math.floor(Math.random() * 40); // 1-1.5 sn arası
game.lastBossBulletTick = LK.ticks;
if (!game.bossBullets) game.bossBullets = [];
}
// Boss 8 saniyede bir bossfire ateşlesin
if (typeof game.lastBossFireTick === "undefined") {
game.lastBossFireTick = LK.ticks;
}
// Bossfire ve bossmermi aynı anda ateşlenmesin
var bossFireJustFired = false;
// --- BOSS 2. FAZ: GÜÇLÜ SALDIRI ---
// 2. fazdaysa, bossfire ve bossmermi saldırılarını güçlendir
if (game.bossPhase === 2) {
// Her 2 saniyede bir spiral/dalga bossmermi ve çoklu bossfire
if (typeof game.bossPhase2AttackTick === "undefined") game.bossPhase2AttackTick = LK.ticks;
if (typeof game.bossPhase2AttackInterval === "undefined") game.bossPhase2AttackInterval = 120;
if (LK.ticks - game.bossPhase2AttackTick > game.bossPhase2AttackInterval) {
// Spiral/dalga bossmermi (5 mermi, farklı açılar)
var spiralCount = 5;
var spiralBaseAngle = LK.ticks % 360 * Math.PI / 180;
for (var s = 0; s < spiralCount; s++) {
var angle = spiralBaseAngle + Math.PI * 2 / spiralCount * s;
var bossBullet = LK.getAsset('bossmermi', {
anchorX: 0.5,
anchorY: 0.5,
x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 40,
y: game.bossImg.y,
width: 48,
height: 48
});
// Spiral hareket: hem sola hem açılı
var speed = 11 + Math.random() * 2;
bossBullet.vx = -speed * Math.cos(angle);
bossBullet.vy = speed * Math.sin(angle) * 0.7;
bossBullet.update = function (bullet) {
return function () {
bullet.x += bullet.vx;
bullet.y += bullet.vy;
};
}(bossBullet);
if (!game.bossBullets) game.bossBullets = [];
game.bossBullets.push(bossBullet);
game.addChild(bossBullet);
}
// Çoklu bossfire (daha geniş yay, daha hızlı)
var fireCount = 5;
var spread = 220;
for (var f = 0; f < fireCount; f++) {
var offsetY = -spread / 2 + spread / (fireCount - 1) * f;
var bossFire = LK.getAsset('bossfire', {
anchorX: 0.5,
anchorY: 0.5,
x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 60,
y: game.bossImg.y + offsetY,
width: 90,
height: 90
});
var speedFire = 16 + Math.random() * 2;
bossFire.vx = -speedFire;
bossFire.vy = 0;
bossFire.burning = false;
bossFire.burnTicks = 0;
bossFire.update = function (fire) {
return function () {
fire.x += fire.vx;
fire.y += fire.vy;
if (fire.burning) {
fire.alpha = 0.7 + 0.3 * Math.sin(LK.ticks / 4);
}
};
}(bossFire);
if (!game.bossFires) game.bossFires = [];
game.bossFires.push(bossFire);
game.addChild(bossFire);
}
game.bossPhase2AttackTick = LK.ticks;
bossFireJustFired = true;
}
}
// 1. faz veya 2. fazda normal bossfire
if (!bossFireJustFired && LK.ticks - game.lastBossFireTick > 480) {
// 8 saniye (60fps*8=480)
// Bossfire aynı anda birkaç kez ateşlensin
var fireCount = 3 + Math.floor(Math.random() * 2); // 3 veya 4 tane
var spread = 120; // Y ekseninde yayılma mesafesi
for (var f = 0; f < fireCount; f++) {
var offsetY = -spread / 2 + spread / (fireCount - 1) * f;
var bossFire = LK.getAsset('bossfire', {
anchorX: 0.5,
anchorY: 0.5,
x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 60,
y: game.bossImg.y + offsetY,
width: 80,
height: 80
});
// Bossfire sadece sola doğru hareket etsin
var speedFire = 13; // bossfire biraz hızlı gitsin
bossFire.vx = -speedFire;
bossFire.vy = 0;
// Yanıcı (yakıcı) etki: çarptığında oyuncuya bir süre daha hasar vermeye devam etsin
bossFire.burning = false;
bossFire.burnTicks = 0;
bossFire.update = function (fire) {
return function () {
fire.x += fire.vx;
fire.y += fire.vy;
// Yanıcı etki aktifse, görsel olarak hafif kırmızıya tintlenebilir (isteğe bağlı)
if (fire.burning) {
fire.alpha = 0.7 + 0.3 * Math.sin(LK.ticks / 4);
}
};
}(bossFire);
if (!game.bossFires) game.bossFires = [];
game.bossFires.push(bossFire);
game.addChild(bossFire);
}
game.lastBossFireTick = LK.ticks;
bossFireJustFired = true;
}
// Boss mermisi ateşle
if (!bossFireJustFired && LK.ticks - game.lastBossBulletTick > game.bossBulletCooldown) {
// Boss'un ateşleme slotları: üstten alta eşit aralıklı hizalı slotlar
var slotCount = 5;
var slotOffsets = [];
var bossImgHeight = game.bossImg.height || 400;
var slotSpacing = bossImgHeight / (slotCount + 1);
for (var si = 0; si < slotCount; si++) {
// slotlar boss görselinin üstünden altına eşit aralıklı
var slotY = -bossImgHeight / 2 + slotSpacing * (si + 1);
slotOffsets.push({
y: slotY,
angle: 0 // düz gitsin, dağınık olmasın
});
}
for (var si = 0; si < slotOffsets.length; si++) {
var slot = slotOffsets[si];
var bossBullet = LK.getAsset('bossmermi', {
anchorX: 0.5,
anchorY: 0.5,
x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 40,
y: game.bossImg.y + slot.y,
width: 48,
height: 48
});
// Boss mermileri sadece sola doğru gitsin
var speed = 10; // Reduced boss bullet speed
bossBullet.vx = -speed;
bossBullet.vy = 0;
bossBullet.update = function (bullet) {
return function () {
bullet.x += bullet.vx;
bullet.y += bullet.vy;
};
}(bossBullet);
game.bossBullets.push(bossBullet);
game.addChild(bossBullet);
}
game.lastBossBulletTick = LK.ticks;
game.bossBulletCooldown = 60 + Math.floor(Math.random() * 40);
}
// Bossfire mermilerini güncelle ve çarpışma kontrolü
if (game.bossFires) {
for (var bf = game.bossFires.length - 1; bf >= 0; bf--) {
var fire = game.bossFires[bf];
if (fire.update) fire.update();
// Ekran dışıysa sil
if (fire.x < -150 || fire.x > 2048 + 150 || fire.y < -150 || fire.y > 2732 + 150) {
fire.destroy();
game.bossFires.splice(bf, 1);
continue;
}
// Oyuncuya çarptı mı?
if (isCircleHit(fire, playerShip)) {
// Eğer bossfire zaten yanıcı değilse, yanıcı etki başlat
if (!fire.burning) {
fire.burning = true;
fire.burnTicks = 0;
fire.burnMaxTicks = 90; // 1.5 saniye boyunca yanıcı etki (60fps*1.5)
fire.burnDamageInterval = 18; // Her 0.3 saniyede bir hasar uygula
fire.lastBurnDamageTick = LK.ticks;
// Patlama efekti
var bossFireHit = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width || 140,
height: playerShip.height || 100
});
game.addChild(bossFireHit);
tween(bossFireHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
bossFireHit.destroy();
}
});
// Kalkan power-up aktifse ilk hasarı engelle
if (activePowerUp === "shield" && playerShip._shielded) {
playerShip._shielded = false;
if (playerShip._shieldCircle) {
tween(playerShip._shieldCircle, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
playerShip._shieldCircle.destroy();
playerShip._shieldCircle = null;
}
});
}
var shieldHit = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width * 1.7,
height: playerShip.height * 1.7
});
shieldHit.alpha = 0.5;
shieldHit.color = 0x7cbb37;
game.addChild(shieldHit);
tween(shieldHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
shieldHit.destroy();
}
});
// Hasarı engelle, can azalmasın
} else {
setPlayerHealth(playerHealth - 5); // bossfire hasarı 5
}
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
}
// Yanıcı etkiyi oyuncunun üstünde bırak, mermiyi hemen yok etme
// Mermiyi ekranda bırak, yanıcı etki bitince yok edilecek
continue;
}
// Yanıcı (yakıcı) bossfire oyuncunun üstündeyse, periyodik hasar uygula
if (fire.burning) {
fire.burnTicks++;
// Her burnDamageInterval tick'te bir hasar uygula
if (fire.burnTicks === 1 || fire.burnTicks % fire.burnDamageInterval === 0) {
setPlayerHealth(playerHealth - 1);
// Yanıcı efektin üstünde küçük bir alev efekti gösterebiliriz (isteğe bağlı)
var burnEffect = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: 80,
height: 80
});
burnEffect.alpha = 0.5;
game.addChild(burnEffect);
tween(burnEffect, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onFinish: function onFinish() {
burnEffect.destroy();
}
});
if (playerHealth <= 0) {
updateCanBar();
LK.showGameOver();
return;
}
}
// Yanıcı etki süresi dolduysa bossfire'ı yok et
if (fire.burnTicks > fire.burnMaxTicks) {
fire.destroy();
game.bossFires.splice(bf, 1);
continue;
}
}
}
}
// Boss mermilerini güncelle ve çarpışma kontrolü
for (var bb = game.bossBullets.length - 1; bb >= 0; bb--) {
var bBullet = game.bossBullets[bb];
if (bBullet.update) bBullet.update();
// Ekran dışıysa sil
if (bBullet.x < -100 || bBullet.x > 2048 + 100 || bBullet.y < -100 || bBullet.y > 2732 + 100) {
bBullet.destroy();
game.bossBullets.splice(bb, 1);
continue;
}
// Oyuncuya çarptı mı?
if (isCircleHit(bBullet, playerShip)) {
// Patlama efekti
var bossBulletHit = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width || 140,
height: playerShip.height || 100
});
game.addChild(bossBulletHit);
tween(bossBulletHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
bossBulletHit.destroy();
}
});
// Kalkan power-up aktifse ilk hasarı engelle
if (activePowerUp === "shield" && playerShip._shielded) {
playerShip._shielded = false;
if (playerShip._shieldCircle) {
tween(playerShip._shieldCircle, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
playerShip._shieldCircle.destroy();
playerShip._shieldCircle = null;
}
});
}
var shieldHit = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width * 1.7,
height: playerShip.height * 1.7
});
shieldHit.alpha = 0.5;
shieldHit.color = 0x7cbb37;
game.addChild(shieldHit);
tween(shieldHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
shieldHit.destroy();
}
});
// Hasarı engelle, can azalmasın
} else {
setPlayerHealth(playerHealth - 3); // bossmermi hasarı 3
}
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
bBullet.destroy();
game.bossBullets.splice(bb, 1);
continue;
}
}
// Boss'un hareket yarıçapı: ekranın sağ yarısında, merkeze kadar gidebilsin
// Merkez: (2048/2, 2732/2)
// Boss'un hareket merkezi: ekranın sağında başlar, merkeze kadar hareket edebilir
var centerX = 2048 / 2;
var centerY = 2732 / 2;
var rightEdgeX = 2048 - 200;
var bossMoveRadiusX = (rightEdgeX - centerX) / 2; // sağdan merkeze kadar yarıçap
var bossMoveRadiusY = (centerY - 0) * 0.8; // üstten alta merkeze kadar (biraz daha az)
var bossCenterX = centerX + bossMoveRadiusX;
var bossCenterY = centerY;
// --- BOSS MERMİLERİNDEN KAÇMA ALGORİTMASI KALDIRILDI ---
// Boss, ekrandaki boss mermilerinden kaçmaz, sadece dairesel hareket yapar
var t = LK.ticks / 60; // yavaş hareket için
var bossTargetX = bossCenterX + Math.cos(t) * bossMoveRadiusX;
var bossTargetY = bossCenterY + Math.sin(t * 0.8) * bossMoveRadiusY;
// Boss'un hedef pozisyonuna yumuşak geçiş (smooth movement)
var lerp = function lerp(a, b, t) {
return a + (b - a) * t;
};
game.bossImg.x = lerp(game.bossImg.x, bossTargetX, 0.18);
game.bossImg.y = lerp(game.bossImg.y, bossTargetY, 0.18);
// --- BOSS CAN, HASAR ALMA, HASAR VERME ---
// Boss canı başlat
if (typeof game.bossHealth === "undefined") {
game.bossMaxHealth = 30; // Boss'un toplam canı artık 30 (daha zor)
game.bossHealth = game.bossMaxHealth;
// Boss can barı
game.bossHealthBarBg = new Container();
var bossBarBgRect = game.bossHealthBarBg.attachAsset('can', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 20,
width: 400,
height: 40
});
bossBarBgRect.alpha = 0.25;
game.bossHealthBarFg = new Container();
var bossBarFgRect = game.bossHealthBarFg.attachAsset('can', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 20,
width: 400,
height: 40
});
bossBarFgRect.alpha = 1;
game.bossHealthBarContainer = new Container();
game.bossHealthBarContainer.addChild(game.bossHealthBarBg);
game.bossHealthBarContainer.addChild(game.bossHealthBarFg);
// Boss can barı ekranın sağ üst köşesinde, timer'ın hemen altında göster
game.bossHealthBarContainer.x = -400; // Offset for right alignment in gui.topRight
game.bossHealthBarContainer.y = 100; // Just below timer
LK.gui.topRight.addChild(game.bossHealthBarContainer);
}
// Boss can barını güncelle
var bossTargetWidth = 400 * Math.max(0, game.bossHealth) / (game.bossMaxHealth || 30);
tween(game.bossHealthBarFg.children[0], {
width: bossTargetWidth
}, {
duration: 200
});
// Boss can barı rengi: yeşil (full) -> kırmızı (az)
var bossHealthRatio = Math.max(0, Math.min(1, game.bossHealth / (game.bossMaxHealth || 30)));
var br = Math.round(0xFF * (1 - bossHealthRatio));
var bg = Math.round(0xFF * bossHealthRatio);
var bb = 0;
var bossColor = br << 16 | bg << 8 | bb;
tween(game.bossHealthBarFg.children[0], {
color: bossColor
}, {
duration: 200
});
// Boss'a mermi çarpması kontrolü
for (var bi = bullets.length - 1; bi >= 0; bi--) {
var bossBullet = bullets[bi];
// Boss'un çarpışma yarıçapı: görselin yarısı
var bossRadius = (game.bossImg.width || 400) / 2;
var dx = bossBullet.x - game.bossImg.x;
var dy = bossBullet.y - game.bossImg.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < bossRadius + 16) {
// Patlama efekti
var bossHit = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: bossBullet.x,
y: bossBullet.y,
width: 80,
height: 80
});
game.addChild(bossHit);
tween(bossHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
bossHit.destroy();
}
});
// Boss canı azalt
game.bossHealth -= 2;
if (game.bossHealth < 0) game.bossHealth = 0;
// --- BOSS 2. FAZ GEÇİŞİ ---
// Faz geçişi sadece bir kez tetiklensin
if (typeof game.bossPhase === "undefined") {
game.bossPhase = 1;
}
if (game.bossPhase === 1 && game.bossHealth <= (game.bossMaxHealth || 30) / 2) {
// 2. faza geçiş animasyonu ve güçlendirme
game.bossPhase = 2;
// Boss'u kısa süre dokunulmaz yap, renk değiştir, büyüt/küçült animasyonu
if (game.bossImg) {
// Kısa bir parlama ve büyüme/küçülme animasyonu
var oldColor = game.bossImg.color;
tween(game.bossImg, {
scaleX: 1.35,
scaleY: 1.35,
alpha: 0.5,
color: 0xff2e2e // Kırmızımsı bir renk
}, {
duration: 350,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(game.bossImg, {
scaleX: 1.0,
scaleY: 1.0,
alpha: 1,
color: oldColor
}, {
duration: 350,
easing: tween.easeInOut
});
}
});
// Kısa süreli dokunulmazlık (faz geçişi sırasında hasar almasın)
game.bossInvulnerableTicks = 40; // ~0.7 saniye
}
// 2. faz için saldırı güçlendirmeleri
game.bossPhase2AttackTick = LK.ticks;
game.bossPhase2AttackInterval = 120; // Her 2 saniyede bir özel saldırı
// Boss mermileri ve bossfire daha sık ve daha hızlı olacak
game.bossBulletCooldown = 30 + Math.floor(Math.random() * 20); // Daha sık ateş
}
// Faz geçişi sırasında boss hasar almasın
if (game.bossInvulnerableTicks && game.bossInvulnerableTicks > 0) {
game.bossInvulnerableTicks--;
// Mermiyi yok et ama boss canı azaltma
bossBullet.destroy();
bullets.splice(bi, 1);
continue;
}
// Boss öldü mü?
if (game.bossHealth <= 0) {
// Boss patlama efekti
var bossExplosion = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: game.bossImg.x,
y: game.bossImg.y,
width: game.bossImg.width || 400,
height: game.bossImg.height || 400
});
game.addChild(bossExplosion);
tween(bossExplosion, {
alpha: 0,
scaleX: 3,
scaleY: 3
}, {
duration: 800,
onFinish: function onFinish() {
bossExplosion.destroy();
}
});
// Boss'u yok et
if (game.bossImg) {
game.bossImg.destroy();
game.bossImg = null;
}
// Boss can barını yok et
if (game.bossHealthBarContainer) {
game.bossHealthBarContainer.destroy();
game.bossHealthBarContainer = null;
}
// Boss ile ilgili tüm mermileri ve ateşleri yok et
if (game.bossBullets) {
for (var bb = game.bossBullets.length - 1; bb >= 0; bb--) {
if (game.bossBullets[bb]) game.bossBullets[bb].destroy();
}
game.bossBullets = [];
}
if (game.bossFires) {
for (var bf = game.bossFires.length - 1; bf >= 0; bf--) {
if (game.bossFires[bf]) game.bossFires[bf].destroy();
}
game.bossFires = [];
}
// Boss öldüğünde boss ile ilgili tüm objeleri yok et ve elmas puanını 10 arttır
diamondCount += 10;
updateDiamondCounter();
// Boss ile ilgili tüm objeleri yok et
if (game.bossImg) {
game.bossImg.destroy();
game.bossImg = null;
}
if (game.bossHealthBarContainer) {
game.bossHealthBarContainer.destroy();
game.bossHealthBarContainer = null;
}
if (game.bossBullets) {
for (var bb = game.bossBullets.length - 1; bb >= 0; bb--) {
if (game.bossBullets[bb]) game.bossBullets[bb].destroy();
}
game.bossBullets = [];
}
if (game.bossFires) {
for (var bf = game.bossFires.length - 1; bf >= 0; bf--) {
if (game.bossFires[bf]) game.bossFires[bf].destroy();
}
game.bossFires = [];
}
// Boss diamond ve portal spawn işlemleri ve skor bonusu
score += 20;
scoreTxt.setText(score);
updateDifficulty();
// --- BOSS ÖLDÜ: Elmas (diamond) spawn et, oyuncu toplarsa 10 elmas ver ---
if (!game.bossDiamondSpawned) {
// Elmas objesi ekranda bir kez spawn edilir, boss'un öldüğü yerde
if (typeof bossDiamondObj === "undefined") bossDiamondObj = null;
bossDiamondObj = LK.getAsset('diamond', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 200,
y: 2732 / 2,
width: 120,
height: 120
});
bossDiamondObj.alpha = 0.98;
bossDiamondObj.vx = -2.5 + Math.random() * 5; // Hafif sağa/sola hareket
bossDiamondObj.vy = -2 + Math.random() * 4; // Hafif yukarı/aşağı hareket
bossDiamondObj.update = function () {
bossDiamondObj.x += bossDiamondObj.vx;
bossDiamondObj.y += bossDiamondObj.vy;
// Ekran dışına çıkarsa yok et
if (bossDiamondObj.x < -150 || bossDiamondObj.x > 2048 + 150 || bossDiamondObj.y < -150 || bossDiamondObj.y > 2732 + 150) {
bossDiamondObj.destroy();
bossDiamondObj = null;
return;
}
// Oyuncu toplarsa 10 elmas ver
if (playerShip && isCircleHit(bossDiamondObj, playerShip)) {
diamondCount += 10;
updateDiamondCounter();
// Efekt: patlama
var effect = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: bossDiamondObj.x,
y: bossDiamondObj.y,
width: 140,
height: 140
});
effect.alpha = 0.8;
game.addChild(effect);
tween(effect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
effect.destroy();
}
});
bossDiamondObj.destroy();
bossDiamondObj = null;
// Sadece bir kez alınabilsin
game.bossDiamondSpawned = true;
}
};
game.addChild(bossDiamondObj);
game.bossDiamondSpawned = false; // Henüz alınmadı
}
// --- High Score Save on Win ---
addHighScore(score);
// --- PORTAL EKLE ---
if (!game.portal) {
// Portalı ekranın sağında ortalanmış şekilde oluştur, ekran dışına taşmayacak şekilde
var portalWidth = 120;
var portalHeight = 120;
var portalScale = 3.0; // Büyüme sonrası maksimum scale
var portalX = 2048 - portalWidth * portalScale / 2 - 40; // Sağdan 40px boşluk bırak
var portalY = 2732 / 2;
var portal = LK.getAsset('portal', {
anchorX: 0.5,
anchorY: 0.5,
x: portalX,
y: portalY,
width: portalWidth,
height: portalHeight
});
portal.scaleX = 1.2;
portal.scaleY = 1.2;
portal.alpha = 1;
portal.isShrinking = false;
portal.lastWasIntersecting = false;
game.portal = portal;
game.addChild(portal);
// Portal büyüme animasyonu: 1.2'den 3.0'a kadar büyüsün
portal._growTweenStarted = true;
tween(portal, {
scaleX: 3.0,
scaleY: 3.0
}, {
duration: 1200,
easing: tween.easeOut,
onFinish: function onFinish() {
portal._growTweenStarted = false;
// --- EKRAN DARALTMA: Boss öldükten sonra üstten ve alttan siyah barlar gelsin ---
if (!game._screenNarrowed) {
// Bar yüksekliği: toplam 600px (üst 300, alt 300) gibi, animasyonlu gelsin
var barHeight = 0;
var targetBarHeight = 300;
// Üst bar
var topBar = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 1
});
topBar.alpha = 0.95;
topBar.color = 0x000000;
// Alt bar
var bottomBar = LK.getAsset('background', {
anchorX: 0,
anchorY: 1,
x: 0,
y: 2732,
width: 2048,
height: 1
});
bottomBar.alpha = 0.95;
bottomBar.color = 0x000000;
// Ekrana ekle
game.addChild(topBar);
game.addChild(bottomBar);
// Animasyonla barları büyüt
tween(topBar, {
height: targetBarHeight
}, {
duration: 900,
easing: tween.easeInOut
});
tween(bottomBar, {
height: targetBarHeight,
y: 2732 - targetBarHeight
}, {
duration: 900,
easing: tween.easeInOut
});
// Oyun alanı sınırlarını daraltmak için global değişken
game._screenNarrowed = true;
game._topBar = topBar;
game._bottomBar = bottomBar;
// Oyun alanı sınırlarını güncelle (handleMove ve diğer kontrollerde kullanılabilir)
game._playAreaTop = targetBarHeight;
game._playAreaBottom = 2732 - targetBarHeight;
}
}
});
}
// Oyun bitmesin, win popup gösterme
return;
}
}
}
// Boss oyuncuya çarparsa hasar versin
if (playerShip && game.bossImg) {
var dxp = playerShip.x - game.bossImg.x;
var dyp = playerShip.y - game.bossImg.y;
var distp = Math.sqrt(dxp * dxp + dyp * dyp);
var bossRadius = (game.bossImg.width || 400) / 2;
var playerRadius = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70);
if (distp < bossRadius + playerRadius - 20) {
// Sadece ilk çarpışmada hasar uygula (her frame değil)
if (!game.bossLastPlayerHit) {
// Patlama efekti
var bossPlayerHit = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: playerShip.x,
y: playerShip.y,
width: playerShip.width || 140,
height: playerShip.height || 100
});
game.addChild(bossPlayerHit);
tween(bossPlayerHit, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
bossPlayerHit.destroy();
}
});
setPlayerHealth(playerHealth - 5);
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
game.bossLastPlayerHit = true;
}
} else {
game.bossLastPlayerHit = false;
}
}
}
// (Geri alındı: scrollX += scrollSpeed ile sağa doğru ilerleme efekti yok)
// --- Ava: playerShip ve portal da scrollX ile sağa kaymalı (otomatik hareket yoksa) ---
// (Geri alındı: playerShip ve portal scrollSpeed ile sağa kaydırılmıyor)
// Portal dinamik efekt: sadece büyüme ve renk döngüsü (nabız efekti kaldırıldı)
if (game.portal) {
// Portal'ın konumu ve büyümesi: portal ekranın tam ortasında sabit kalır, büyüme animasyonu yok
if (game.portal) {
// Renk döngüsü (HSV'den RGB'ye basit dönüşüm)
var t = LK.ticks % 360 / 360;
var h = t,
s = 0.7,
v = 1.0;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var r, g, b;
switch (i % 6) {
case 0:
r = v, g = q, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = q;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = q, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}
var color = Math.round(r * 255) << 16 | Math.round(g * 255) << 8 | Math.round(b * 255);
game.portal.color = color;
}
if (typeof game.portal.isShrinking === "undefined") game.portal.isShrinking = false;
if (typeof game.portal.lastWasIntersecting === "undefined") game.portal.lastWasIntersecting = false;
// --- Portal büyümesi bittikten sonra playership otomatik geçişi için ek kodlar ---
if (game.portal && !game.portal.isShrinking && !game.portal._autoMoveStarted && !game.portal.lastWasIntersecting) {
// Portal büyüme animasyonu bittiyse (scaleX >= 3.0 - 0.01)
if (!game.portal._growTweenStarted && Math.abs(game.portal.scaleX - 3.0) < 0.01 && playerShip && !playerShip._autoMovingToPortal) {
// Otomatik hareket başlatılmadan önce 2 saniye bekle
game.portal._autoMoveStarted = true;
playerShip._autoMovingToPortal = true;
// Hedef portalın merkezi
var portalTargetX = game.portal.x;
var portalTargetY = game.portal.y;
LK.setTimeout(function () {
// 2 saniye sonra otomatik hareket başlasın
tween(playerShip, {
x: portalTargetX,
y: portalTargetY
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Hareket bittiğinde flag kaldır
playerShip._autoMovingToPortal = false;
}
});
}, 2000);
}
}
// Oyuncu gemisi portal ile temas etti mi?
var portalIntersect = false;
if (playerShip && !game.portal.isShrinking) {
// Portal ve gemi çarpışma kontrolü (daire-çarpışma)
var dx = playerShip.x - game.portal.x;
var dy = playerShip.y - game.portal.y;
var portalRadius = (game.portal.width ? game.portal.width / 2 : 60) * game.portal.scaleX;
var playerRadius = playerShip.radius || (playerShip.width ? playerShip.width / 2 : 70);
var dist = Math.sqrt(dx * dx + dy * dy);
portalIntersect = dist < portalRadius + playerRadius - 10;
if (!game.portal.lastWasIntersecting && portalIntersect) {
// Gemi portalın içine girdi: gemi ve mermiler kaybolsun, portal küçülüp ışık patlamasıyla kaybolsun
// Gemi kaybolsun (görsel olarak)
if (playerShip && playerShip.parent) {
tween(playerShip, {
alpha: 0,
scaleX: 0.2,
scaleY: 0.2
}, {
duration: 400,
onFinish: function onFinish() {
if (playerShip && playerShip.parent) {
playerShip.destroy();
}
}
});
}
// Tüm mermileri kaybolma animasyonuyla yok et
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
if (b && b.parent) {
b.visible = false; // Portal geçildikten sonra mermiler görünmesin
b.alpha = 0;
b.destroy();
}
}
bullets = [];
// Portal küçülmeye başlasın
game.portal.isShrinking = true;
tween(game.portal, {
scaleX: 0.1,
scaleY: 0.1,
alpha: 0.0
}, {
duration: 900,
easing: tween.easeIn,
onFinish: function onFinish() {
// Işık patlaması efekti
if (game.portal && game.portal.parent) {
var portalExplosion = LK.getAsset('portalblast', {
anchorX: 0.5,
anchorY: 0.5,
x: game.portal.x,
y: game.portal.y,
width: (game.portal.width || 120) * (game.portal.scaleX || 1.0) * 2.2,
height: (game.portal.height || 120) * (game.portal.scaleY || 1.0) * 2.2
});
portalExplosion.alpha = 0.85;
game.addChild(portalExplosion);
tween(portalExplosion, {
alpha: 0,
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 500,
onFinish: function onFinish() {
if (portalExplosion && portalExplosion.parent) portalExplosion.destroy();
// Portal tamamen kaybolduktan sonra win ekranı göster
// LK.showYouWin(); // Win ekranı gösterme KALDIRILDI
}
});
game.portal.destroy();
game.portal = null;
}
}
});
}
game.portal.lastWasIntersecting = portalIntersect;
}
}
// Kara delik (BlackHole) özelliği kaldırıldı
// --- Nadiren çıkan diamond objesi için global değişken ve spawn sistemi ---
if (typeof diamondObj === "undefined") diamondObj = null;
if (typeof lastDiamondSpawnTick === "undefined") lastDiamondSpawnTick = -10000;
var diamondSpawnCooldown = 3600 + Math.floor(Math.random() * 1800); // 1-1.5 dakika arası (60fps*60=3600)
if (!diamondObj && LK.ticks - lastDiamondSpawnTick > diamondSpawnCooldown) {
// %7 olasılıkla diamond spawn et (çok nadir)
if (Math.random() < 0.07) {
diamondObj = LK.getAsset('diamond', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 600 + Math.random() * 400 - 200,
y: 400 + Math.random() * (2732 - 800),
width: 100,
height: 100
});
diamondObj.alpha = 0.95;
diamondObj.vx = -3 - Math.random() * 2.5;
diamondObj.vy = (Math.random() - 0.5) * 2.0;
diamondObj.update = function () {
diamondObj.x += diamondObj.vx;
diamondObj.y += diamondObj.vy;
// Ekran dışına çıkarsa yok et
if (diamondObj.x < -150 || diamondObj.x > 2048 + 150 || diamondObj.y < -150 || diamondObj.y > 2732 + 150) {
diamondObj.destroy();
diamondObj = null;
return;
}
};
game.addChild(diamondObj);
lastDiamondSpawnTick = LK.ticks;
} else {
// spawn denemesi başarısızsa tekrar denemek için tick'i güncelleme
lastDiamondSpawnTick = LK.ticks;
}
}
// Gift spawn: gift yoksa ve spawn süresi dolduysa nadiren spawn et
// OYUNUN BAŞINDA HEDİYE/ÖDÜL VERİLMEZ: ilk 10 saniye (600 tick) ödül yok
var minGiftSpawnTick = 600; // 10 saniye (60fps*10)
if (LK.ticks <= minGiftSpawnTick) {
// İlk 10 saniye ödül/gift/diamond verilmeyecek
} else if (!giftBg && LK.ticks - lastGiftSpawnTick > giftSpawnCooldown && LK.ticks > minGiftSpawnTick) {
// Rastgele olasılıkla gift spawn et (ör: %60 olasılık)
if (Math.random() < 0.6) {
spawnGift();
} else {
// spawn denemesi başarısızsa tekrar denemek için tick'i güncelleme
lastGiftSpawnTick = LK.ticks;
}
}
// Gift güncellemesi (power-up çarpışma kontrolü)
if (giftBg && giftBg.update) {
giftBg.update();
}
// Diamond objesi güncellemesi
if (diamondObj && diamondObj.update) {
diamondObj.update();
}
// Boss öldüğünde çıkan diamond objesi güncellemesi
if (typeof bossDiamondObj !== "undefined" && bossDiamondObj && bossDiamondObj.update) {
bossDiamondObj.update();
}
// Aktif power-up süresini kontrol et
if (activePowerUp && LK.ticks >= powerUpEndTick) {
deactivatePowerUp();
}
// Power-up efektleri: hız, kalkan, skor çarpanı
if (activePowerUp === "speedup" && playerShip && dragging) {
// Sürükleme hızını artırmak için handleMove fonksiyonunda hız limiti artırılabilir
// (Burada ek bir kod gerekmez, handleMove zaten sınırları kontrol ediyor)
}
if (activePowerUp === "shield" && playerShip && playerShip._shieldCircle) {
// Kalkan efekti: hafif nabız animasyonu
var t = LK.ticks % 60 / 60;
var scale = 1.3 + 0.1 * Math.sin(t * Math.PI * 2);
playerShip._shieldCircle.scaleX = scale;
playerShip._shieldCircle.scaleY = scale;
}
// Power-up skor çarpanı: skor eklenirken game._scoreMultiplier kullanılır
if (!game._scoreMultiplier) game._scoreMultiplier = 1;
// --- Orijinal kod ---
};
düşman uzay gemisi. In-Game asset. 2d. High contrast. No shadows
patlama efekti. In-Game asset. 2d. High contrast. No shadows
mermi yönünü sağa çevir ve yat
satürn. In-Game asset. 2d. High contrast. No shadows
meteor taşı. In-Game asset. 2d. High contrast. No shadows
bölüm sonu canavar için devasa uzay gemisi. In-Game asset. 2d. High contrast. No shadows
rengini değiştir
ışın mermisi. In-Game asset. 2d. High contrast. No shadows
yanan ateş topları. In-Game asset. 2d. High contrast. No shadows
oyunda açılacak bir uzay portalı için görüntüyü netleştir
A magical sci-fi starburst explosion for a 2D game effect, with a bright blue and white energy core bursting outward in radiant spikes, surrounded by glowing particles, swirling light trails, and a soft nebula-like aura. The effect should feel like a powerful portal discharge or dimensional rift opening, with dynamic energy and cinematic glow. Transparent background, digital art style, top-down angle, ideal for sprite use in games.. In-Game asset. 2d. High contrast. No shadows
A stunning 2D top-down galaxy for a space-themed game background, featuring a massive spiral galaxy with swirling arms in vibrant shades of blue, purple, and pink, a bright glowing core, scattered star clusters, distant nebulae, and a few small planets orbiting around. The galaxy should feel colorful, mysterious, and vast, with soft glowing effects and high contrast for a sci-fi aesthetic. Style: digital art, seamless background, suitable for looping game parallax layers.. In-Game asset. 2d. High contrast. No shadows
kalkanın içinde gemi olmasın
A 2D sci-fi gift box or power-up crate floating in space, with a glowing metallic surface, futuristic design, bright neon blue and silver accents, and a soft pulsing light effect. The box should look valuable and mysterious, slightly levitating with subtle sparkles or energy rings around it. Designed for a top-down space shooter game. Transparent background, digital art, ideal for sprite use.. In-Game asset. 2d. High contrast. No shadows
A 2D sci-fi power-up gift box that grants a shield, designed with a glowing blue energy core inside a metallic futuristic container. The box features holographic shield symbols, neon cyan highlights, and soft pulsing light. It is slightly levitating, surrounded by sparkles and a faint energy ring. The design should clearly suggest it gives protective power. Transparent background, digital art style, ideal for sprite use in a top-down space shooter game.. In-Game asset. 2d. High contrast. No shadows
bu görseli hız için değiştir
Design a basic 2D top-down spaceship with a compact, angular body and minimal detailing. The ship should have a small central cockpit, two modest rear thrusters, and one weapon mount. Colors are simple — grays and blues — suggesting a utilitarian design. It should look like a beginner’s ship: reliable but not advanced. In-Game asset. 2d. High contrast. No shadows
Upgrade the Level 1 ship into a more capable 2D top-down design. Add wing extensions with subtle glowing lines, a larger engine section with animated thrusters, and two visible weapon hardpoints. Add more color variation (blues, steel, light glow effects) to indicate progress and increased power.. In-Game asset. 2d. High contrast. No shadows
Transform the ship into a high-tech 2D top-down spacecraft. Add shield emitters with rotating energy halos, four weapon slots, side thrusters, and an enhanced cockpit with a golden or crystal-like glow. The silhouette is wider and more refined. Visuals should include detailed paneling, moving parts, and advanced energy flows.. In-Game asset. 2d. High contrast. No shadows
elmas. In-Game asset. 2d. High contrast. No shadows
uzay 2d etkileyici lazer ışını. In-Game asset. 2d. High contrast. No shadows