/**** * 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 = -20 - (typeof difficulty !== "undefined" ? (difficulty - 1) * 2.2 : 0); self.vy = (Math.random() - 0.5) * (3.5 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0)); 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 = -24 - (typeof difficulty !== "undefined" ? (difficulty - 1) * 1.7 : 0); // 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 = -22 - (typeof difficulty !== "undefined" ? (difficulty - 1) * 2.0 : 0); self.vy = (Math.random() - 0.5) * (5 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0)); 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 = 10 + (typeof difficulty !== "undefined" ? (difficulty - 1) * 1.7 : 0) + Math.random() * 4.5; self.vx = -baseSpeed; self.vy = (Math.random() - 0.5) * (4.5 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0)); 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: use selected asset if set, otherwise default to 'playerShip' var assetId = typeof game !== "undefined" && game.selectedShipAssetId ? game.selectedShipAssetId : 'playerShip'; var shipAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); // Asset will be created as: ellipse, width: 140, height: 100, color: 0x3a9cff shipAsset.width = 140; shipAsset.height = 100; // playership2 ve playership3 için kendi görseli kullanılsın, renk override etme if (assetId === "playership2" || assetId === "playership3") { // playership2 ve playership3'ün kendi görseli kullanılsın, renk override etme } else { 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 = 18 + (typeof difficulty !== "undefined" ? (difficulty - 1) * 1.7 : 0) + Math.random() * 7; self.vx = -speed; self.vy = (Math.random() - 0.5) * (4 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0)); // daha fazla 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 ****/ // Yıldızlar: Parallax ve hafif dönen yıldızlar // Galaksi arka planı kaldırıldı 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 = ""; // --- 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ı - made in TE"; } 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); // 1. slot ise playership görselini ortala ve sığdır if (row === 0 && col === 0) { // Playership assetini tekrar kullanılabilir şekilde oluştur if (!modalContainer._playershipAsset) { var psMargin = 0.07 * slotSize; var psSize = slotSize - 2 * psMargin; var ps = LK.getAsset('playerShip', { anchorX: 0.5, anchorY: 0.5, x: slotX, y: slotY, width: psSize, height: psSize }); ps.alpha = 1; modalContainer._playershipAsset = ps; } else { // Varsa mevcut asseti yeni konuma taşı var ps = modalContainer._playershipAsset; ps.x = slotX; ps.y = slotY; ps.width = slotSize - 2 * (0.07 * slotSize); ps.height = slotSize - 2 * (0.07 * slotSize); ps.alpha = 1; } modalContainer.addChild(ps); } // 2. slot ise playership2 görselini ortala ve sığdır if (row === 0 && col === 1) { // 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); } // 3. slot ise playership3 görselini ortala ve sığdır if (row === 0 && col === 2) { 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 = [0, 100, 0]; // 1. slot ücretsiz, 2. slot 100 elmas, 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(); } }); // Satın al butonunu kaldır, yerine kullan butonu ekle if (btnRef && btnRef.parent) { var parent = btnRef.parent; var btnX = btnRef.x; var btnY = btnRef.y; var btnW = btnRef.width; var btnH = btnRef.height; // Fiyat etiketini kaldır for (var ci = 0; ci < parent.children.length; ci++) { var child = parent.children[ci]; if (child && child instanceof Text2 && child.text && (child.text.indexOf("+") !== -1 || child.text === price + "")) { child.destroy(); // parent.children.splice(ci, 1); // Gerek yok, destroy yeterli } } // Satın al butonunu kaldır btnRef.destroy(); // "Kullan" butonu ekle var useBtn = LK.getAsset('can', { anchorX: 0.5, anchorY: 0.5, x: btnX, y: btnY, width: btnW, height: btnH }); // Hangi slotun hangi gemiye ait olduğunu belirle var shipName = ""; if (col === 0) { shipName = "playerShip"; } else if (col === 1) { shipName = "playership2"; } else if (col === 2) { shipName = "playership3"; } else { shipName = ""; } // Seçili gemiyle karşılaştır, aktifse butonu pasif yap var isSelected = (game.selectedShipAssetId ? game.selectedShipAssetId : "playerShip") === shipName; if (isSelected) { useBtn.alpha = 0.45; useBtn.color = 0x888888; useBtn.interactive = false; } else { useBtn.alpha = 0.92; useBtn.color = 0x7cbb37; useBtn.interactive = true; useBtn.defaultAlpha = useBtn.alpha; useBtn.down = function (btnRef) { return function (x, y, obj) { btnRef.alpha = 0.65; tween(btnRef, { alpha: btnRef.defaultAlpha }, { duration: 120 }); var usedText = new Text2("Kullanıldı!", { size: 36, fill: 0x3a9cff }); usedText.anchor.set(0.5, 0.5); usedText.x = btnRef.x; usedText.y = btnRef.y - 48; modalContainer.addChild(usedText); tween(usedText, { alpha: 0 }, { duration: 900, onFinish: function onFinish() { usedText.destroy(); } }); // --- Aktif gemiyi değiştir --- // shipName'i kullanarak ilgili gemiyi aktif et var newShipAssetId = shipName && typeof shipName === "string" && shipName.length > 0 ? shipName : "playerShip"; game.selectedShipAssetId = newShipAssetId; // Eski gemiyi yok et if (typeof playerShip !== "undefined" && playerShip && playerShip.parent) { playerShip.destroy(); } // Yeni gemiyi oluştur ve ekle playerShip = new PlayerShip(); // Gemiyi uygun pozisyona yerleştir playerShip.x = 350; playerShip.y = 2732 / 2; game.addChild(playerShip); // Sağlık barı ve diğer göstergeleri güncelle // Seçilen gemiye göre max health güncelle if (game.selectedShipAssetId === "playership2") { playerMaxHealth = 15; } else if (game.selectedShipAssetId === "playership3") { playerMaxHealth = 20; } else { playerMaxHealth = 10; } setPlayerHealth(playerMaxHealth); updateCanBar(); updatePlayershipCanBar(); // Mağaza slotlarındaki tüm "Kullan" butonlarını güncelle (aktif/pasif) if (parent && parent.children) { for (var ci = 0; ci < parent.children.length; ci++) { var child = parent.children[ci]; if (child && child !== btnRef && child.down && typeof child.interactive !== "undefined") { // Sadece diğer "Kullan" butonlarını pasif yap child.alpha = 0.45; child.color = 0x888888; child.interactive = false; } } // Seçilen butonu aktif yap btnRef.alpha = 0.45; btnRef.color = 0x888888; btnRef.interactive = false; } }; }(useBtn); } parent.addChild(useBtn); // "Kullan" butonu yazısı var useBtnLabel = ""; if (shipName === "playerShip") { useBtnLabel = "playership Kullan"; } else if (shipName === "playership2") { useBtnLabel = "playership2 Kullan"; } else if (shipName === "playership3") { useBtnLabel = "playership3 Kullan"; } else { useBtnLabel = "Kullan"; } var useBtnText = new Text2(useBtnLabel, { size: 32, fill: "#fff" }); useBtnText.anchor.set(0.5, 0.5); useBtnText.x = useBtn.x; useBtnText.y = useBtn.y; useBtnText.interactive = !isSelected; useBtnText.down = function (btnRef) { return function (x, y, obj) { if (btnRef && btnRef.down) btnRef.down(x, y, obj); }; }(useBtn); parent.addChild(useBtnText); } }; }(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 oyunda görünmesin, sadece bossDiamondObj ile elmas verilsin if (diamondObj) { 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 if (typeof game !== "undefined" && game.selectedShipAssetId === "playership2") { playerMaxHealth = 15; // playership2 için sağlık 15 olsun } else if (typeof game !== "undefined" && game.selectedShipAssetId === "playership3") { playerMaxHealth = 20; // playership3 için sağlık 20 olsun } 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 = 2; // Başlangıç zorluğu 2 olsun var spawnInterval = 80; // ticks, daha hızlı başlasın var lastSpawnTick = 0; shootInterval = 180; // daha hızlı 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 (storage'dan yükle, yoksa 0) 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 + ""); // Elmas sayısını storage'a kaydet storage.diamondCount = 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 // Ava: Skor panelinin kaybolmasını engellemek için her frame tekrar ekle if (!game._scoreDiamondContainerCheckAdded) { game._scoreDiamondContainerCheckAdded = true; game.updateScoreDiamondContainerVisibility = function () { if (!scoreDiamondContainer.parent) { LK.gui.top.addChild(scoreDiamondContainer); } scoreDiamondContainer.visible = true; scoreTxt.visible = true; diamondCounterContainer.visible = true; }; // Her frame kontrol et var _scoreDiamondContainerInterval = LK.setInterval(function () { if (typeof game.updateScoreDiamondContainerVisibility === "function") { game.updateScoreDiamondContainerVisibility(); } }, 200); } // 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 && typeof game.enemiesKilled !== "undefined" && game.enemiesKilled >= 20) { // Only allow one enemyship2 on screen at a time (use ._isEnemyship2 flag for reliability) var hasEnemyship2 = false; for (var i = 0; i < spaceObjects.length; i++) { var so = spaceObjects[i]; if (so && so._isEnemyship2) { hasEnemyship2 = true; break; } } if (hasEnemyship2) { // Do not spawn another enemyship2 return; } // enemyship2 (yeni düşman tipi) obj = new Container(); obj._isEnemyship2 = true; // Reliable type flag for enemyship2 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-20 arası, her 3 puanda bir artar, maksimum 20 (daha hızlı ve daha yüksek artış) var newDifficulty = 1 + Math.floor(score / 3); if (newDifficulty > 20) newDifficulty = 20; if (newDifficulty > difficulty) { difficulty = newDifficulty; } // spawnInterval: Kolayda yavaş (60), zorda çok hızlı (4) // 1. zorlukta 60, 20. zorlukta 4 spawnInterval = Math.round(60 - (difficulty - 1) * 2.9); if (spawnInterval < 4) spawnInterval = 4; // Mermi hızını ve ateş sıklığını zorlukla birlikte daha fazla artır // shootInterval: 1. zorlukta 120, 20. zorlukta 12 shootInterval = Math.round(120 - (difficulty - 1) * 5.7); if (shootInterval < 12) shootInterval = 12; // 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._isEnemyship2) { // enemyship2 ise 3 birim hasar 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._isEnemyship2) { // 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._isEnemyship2) { scoreToAdd = 5; } // EnemyShip (eski tip) 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; // --- Bossfire spiral ve dairesel atış kaldırıldı, sadece klasik yayılma atışı kaldı --- if (!bossFireJustFired && LK.ticks - game.lastBossFireTick > 480) { // 8 saniye (60fps*8=480) // Sadece klasik yayılma atışı 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: 80, height: 80 }); bossFire.vx = -13; 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.lastBossFireTick = LK.ticks; bossFireJustFired = true; } // Boss mermisi ateşle if (!bossFireJustFired && LK.ticks - game.lastBossBulletTick > game.bossBulletCooldown) { // --- GELİŞTİRİLMİŞ: Zigzag ve spiral boss mermileri --- var slotCount = 5; var slotOffsets = []; var bossImgHeight = game.bossImg.height || 400; var slotSpacing = bossImgHeight / (slotCount + 1); for (var si = 0; si < slotCount; si++) { var slotY = -bossImgHeight / 2 + slotSpacing * (si + 1); slotOffsets.push({ y: slotY, angle: 0 }); } // Zigzag boss mermileri 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 }); // Zigzag için başlangıç fazı bossBullet._zigzagPhase = Math.random() * Math.PI * 2; bossBullet._zigzagSpeed = 2.5 + Math.random() * 1.5; bossBullet._zigzagAmp = 38 + Math.random() * 22; var speed = 10; bossBullet.vx = -speed; bossBullet.vy = 0; bossBullet._baseY = bossBullet.y; bossBullet._bornTick = LK.ticks; bossBullet.update = function (bullet) { return function () { bullet.x += bullet.vx; // Zigzag hareket: y = baseY + amp * sin(frekans * t + faz) var t = (LK.ticks - bullet._bornTick) / 12; bullet.y = bullet._baseY + Math.sin(t * bullet._zigzagSpeed + bullet._zigzagPhase) * bullet._zigzagAmp; }; }(bossBullet); game.bossBullets.push(bossBullet); game.addChild(bossBullet); } // Spiral boss mermileri (daha zor için) if (game.bossHealth < game.bossMaxHealth * 0.5) { var spiralCount = 8; var spiralRadius = 0; var spiralSpeed = 7; for (var sp = 0; sp < spiralCount; sp++) { var angle = Math.PI * 2 / spiralCount * sp + LK.ticks % 60 / 60 * Math.PI * 2; var spiralBullet = LK.getAsset('bossmermi', { anchorX: 0.5, anchorY: 0.5, x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 40, y: game.bossImg.y, width: 40, height: 40 }); spiralBullet._angle = angle; spiralBullet._radius = spiralRadius; spiralBullet._speed = spiralSpeed; spiralBullet._bornTick = LK.ticks; spiralBullet.update = function (bullet) { return function () { // Spiral hareket: açı artar, x ve y ona göre değişir bullet._angle += 0.07; bullet.x += Math.cos(bullet._angle) * bullet._speed - 6; bullet.y += Math.sin(bullet._angle) * bullet._speed; }; }(spiralBullet); game.bossBullets.push(spiralBullet); game.addChild(spiralBullet); } } 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 - 8); // bossfire hasarı 8 (daha fazla) } 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 - 6); // bossmermi hasarı 6 (daha fazla) } 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; // --- GELİŞTİRİLMİŞ: Boss hareketine ileri-geri ve yukarı-aşağı dalga ekle --- var t = LK.ticks / 60; // yavaş hareket için var bossTargetX = bossCenterX + Math.cos(t) * bossMoveRadiusX + Math.sin(t * 2.2) * 60; var bossTargetY = bossCenterY + Math.sin(t * 0.8) * bossMoveRadiusY + Math.cos(t * 1.7) * 40; 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 = 200; // Boss'un toplam canı artık 200 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ÇİŞİ --- // Boss faz 2 iptal: Boss her zaman faz 1'de kalacak, faz geçişi ve faz 2 saldırı güçlendirmeleri kaldırıldı. if (typeof game.bossPhase === "undefined") { game.bossPhase = 1; } // 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Ü: Portalı aktif et --- 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; } } }); } return; // Elmas sadece skor panelinde gösterilecek, oyun alanında diamond objesi spawn edilmez. // --- 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 - 10); // boss çarpışma hasarı 10 (daha fazla) 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 // --- Ava: Ekrana 'continius' yazısı ekle --- var continiusText = new Text2("continius", { size: 140, fill: 0xFFE066, font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'", maxWidth: 1800 }); continiusText.anchor.set(0.5, 0.5); continiusText.x = 2048 / 2; continiusText.y = 2732 / 2; continiusText.alpha = 0; game.addChild(continiusText); tween(continiusText, { alpha: 1 }, { duration: 800, onFinish: function onFinish() { // Birkaç saniye sonra yavaşça kaybolsun tween(continiusText, { alpha: 0 }, { duration: 1800, delay: 2200, onFinish: function onFinish() { if (continiusText && continiusText.parent) continiusText.destroy(); } }); } }); } }); game.portal.destroy(); game.portal = null; } } }); } game.portal.lastWasIntersecting = portalIntersect; } } // --- Black Hole (Kara Delik) Mekaniği --- // Kara delik objesi ve spawn kontrolü if (typeof blackHoleObj === "undefined") blackHoleObj = null; if (typeof lastBlackHoleSpawnTick === "undefined") lastBlackHoleSpawnTick = -10000; var blackHoleSpawnCooldown = 4200 + Math.floor(Math.random() * 1800); // 70-100 sn arası if (!blackHoleObj && LK.ticks - lastBlackHoleSpawnTick > blackHoleSpawnCooldown) { // %5 olasılıkla kara delik spawn et (çok nadir) if (Math.random() < 0.05) { blackHoleObj = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 400 + Math.random() * 400 - 200, y: 400 + Math.random() * (2732 - 800), width: 180, height: 180 }); blackHoleObj.alpha = 0.7; blackHoleObj.color = 0x222233; blackHoleObj.vx = -2.5 - Math.random() * 2.5; blackHoleObj.vy = (Math.random() - 0.5) * 2.0; blackHoleObj.radius = 90; blackHoleObj._pullStrength = 0.7 + Math.random() * 0.5; blackHoleObj._lifetime = 900 + Math.floor(Math.random() * 600); // 15-25 sn ekranda kalır blackHoleObj._spawnTick = LK.ticks; blackHoleObj.update = function () { // Hareket blackHoleObj.x += blackHoleObj.vx; blackHoleObj.y += blackHoleObj.vy; // Ekran dışına çıkarsa yok et if (blackHoleObj.x < -200 || blackHoleObj.x > 2048 + 200 || blackHoleObj.y < -200 || blackHoleObj.y > 2732 + 200) { blackHoleObj.destroy(); blackHoleObj = null; return; } // Süresi dolduysa yok et if (LK.ticks - blackHoleObj._spawnTick > blackHoleObj._lifetime) { // Fade out tween(blackHoleObj, { alpha: 0 }, { duration: 600, onFinish: function onFinish() { if (blackHoleObj && blackHoleObj.parent) blackHoleObj.destroy(); blackHoleObj = null; } }); return; } // Kara delik çekim etkisi: yakınındaki objeleri kendine çeker var pullRadius = 420; // Uzay cisimleri for (var i = 0; i < spaceObjects.length; i++) { var so = spaceObjects[i]; if (!so || !so.x || !so.y) continue; var dx = blackHoleObj.x - so.x; var dy = blackHoleObj.y - so.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < pullRadius && dist > 1) { var pull = blackHoleObj._pullStrength * (1 - dist / pullRadius); so.vx += dx / dist * pull; so.vy += dy / dist * pull; } } // Mermiler for (var i = 0; i < bullets.length; i++) { var b = bullets[i]; if (!b || !b.x || !b.y) continue; var dx = blackHoleObj.x - b.x; var dy = blackHoleObj.y - b.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < pullRadius && dist > 1) { var pull = blackHoleObj._pullStrength * 0.7 * (1 - dist / pullRadius); b.speed *= 0.98; // Kara delik yakınında mermiler yavaşlar b.x += dx / dist * pull * 0.7; b.y += dy / dist * pull * 0.7; } } // Oyuncu gemisi if (playerShip && playerShip.x && playerShip.y) { var dx = blackHoleObj.x - playerShip.x; var dy = blackHoleObj.y - playerShip.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < pullRadius && dist > 1) { var pull = blackHoleObj._pullStrength * 0.5 * (1 - dist / pullRadius); // Sürüklenmiyorsa gemiyi hafifçe çeksin if (!dragging && !playerShip._autoMovingToPortal) { playerShip.x += dx / dist * pull; playerShip.y += dy / dist * pull; } } // Kara deliğe çok yaklaşırsa (merkezine), anında yok olma if (dist < blackHoleObj.radius + (playerShip.radius || 70) - 10) { // Patlama efekti var bhExpl = 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(bhExpl); tween(bhExpl, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { bhExpl.destroy(); } }); setPlayerHealth(0); if (playerHealth <= 0) { LK.showGameOver(); return; } } } // Hafif nabız efekti var t = LK.ticks % 60 / 60; var scale = 1.0 + 0.08 * Math.sin(t * Math.PI * 2); blackHoleObj.scaleX = scale; blackHoleObj.scaleY = scale; }; game.addChild(blackHoleObj); lastBlackHoleSpawnTick = LK.ticks; } else { // spawn denemesi başarısızsa tekrar denemek için tick'i güncelleme lastBlackHoleSpawnTick = LK.ticks; } } // Kara delik güncellemesi if (blackHoleObj && blackHoleObj.update) { blackHoleObj.update(); } // --- 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; } } // --- Time Freeze Power-up (Zamanı Dondur) --- // Sadece bir tane ekranda olabilir if (typeof timeFreezeObj === "undefined") timeFreezeObj = null; if (typeof lastTimeFreezeSpawnTick === "undefined") lastTimeFreezeSpawnTick = -10000; var timeFreezeSpawnCooldown = 2400 + Math.floor(Math.random() * 1200); // 40-60 sn arası if (!timeFreezeObj && LK.ticks - lastTimeFreezeSpawnTick > timeFreezeSpawnCooldown) { // %08 olasılıkla zaman dondur spawn et if (Math.random() < 0.08) { timeFreezeObj = LK.getAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 400 + Math.random() * 400 - 200, y: 400 + Math.random() * (2732 - 800), width: 120, height: 120 }); timeFreezeObj.alpha = 0.92; timeFreezeObj.color = 0x66e0ff; timeFreezeObj.vx = -3 - Math.random() * 2.5; timeFreezeObj.vy = (Math.random() - 0.5) * 2.0; timeFreezeObj.radius = 60; timeFreezeObj._lifetime = 600 + Math.floor(Math.random() * 400); // 10-16 sn ekranda kalır timeFreezeObj._spawnTick = LK.ticks; timeFreezeObj.update = function () { timeFreezeObj.x += timeFreezeObj.vx; timeFreezeObj.y += timeFreezeObj.vy; // Ekran dışına çıkarsa yok et if (timeFreezeObj.x < -150 || timeFreezeObj.x > 2048 + 150 || timeFreezeObj.y < -150 || timeFreezeObj.y > 2732 + 150) { timeFreezeObj.destroy(); timeFreezeObj = null; return; } // Süresi dolduysa yok et if (LK.ticks - timeFreezeObj._spawnTick > timeFreezeObj._lifetime) { tween(timeFreezeObj, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { if (timeFreezeObj && timeFreezeObj.parent) timeFreezeObj.destroy(); timeFreezeObj = null; } }); return; } // Oyuncu toplarsa zamanı dondur if (playerShip && isCircleHit(timeFreezeObj, playerShip)) { // Efekt: patlama var tfEffect = LK.getAsset('patlamaeffekt', { anchorX: 0.5, anchorY: 0.5, x: timeFreezeObj.x, y: timeFreezeObj.y, width: 120, height: 120 }); tfEffect.alpha = 0.7; game.addChild(tfEffect); tween(tfEffect, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 400, onFinish: function onFinish() { tfEffect.destroy(); } }); // Zamanı dondur: tüm düşmanlar ve mermiler 3 saniye boyunca hareket etmesin game._timeFreezeActive = true; game._timeFreezeEndTick = LK.ticks + 180; // 3 saniye // Görsel: ekranın üstünde "Zaman Dondu!" yazısı var freezeText = new Text2("Zaman Dondu!", { size: 110, fill: 0x66e0ff, font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'", maxWidth: 1800 }); freezeText.anchor.set(0.5, 0.5); freezeText.x = 2048 / 2; freezeText.y = 2732 / 2 - 300; freezeText.alpha = 0; game.addChild(freezeText); tween(freezeText, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { tween(freezeText, { alpha: 0 }, { duration: 800, delay: 1800, onFinish: function onFinish() { if (freezeText && freezeText.parent) freezeText.destroy(); } }); } }); timeFreezeObj.destroy(); timeFreezeObj = null; } // Hafif parıltı efekti var t = LK.ticks % 60 / 60; var scale = 1.0 + 0.12 * Math.sin(t * Math.PI * 2); timeFreezeObj.scaleX = scale; timeFreezeObj.scaleY = scale; }; game.addChild(timeFreezeObj); lastTimeFreezeSpawnTick = LK.ticks; } else { lastTimeFreezeSpawnTick = LK.ticks; } } // Time freeze güncellemesi if (timeFreezeObj && timeFreezeObj.update) { timeFreezeObj.update(); } // Time freeze aktifse, düşmanlar ve mermiler hareket etmesin if (game._timeFreezeActive) { if (LK.ticks >= game._timeFreezeEndTick) { game._timeFreezeActive = false; } else { // Düşmanlar ve mermiler update fonksiyonlarını atla for (var i = 0; i < spaceObjects.length; i++) { if (spaceObjects[i]) spaceObjects[i].vx = 0, spaceObjects[i].vy = 0; } if (game.enemyBullets) { for (var i = 0; i < game.enemyBullets.length; i++) { if (game.enemyBullets[i]) game.enemyBullets[i].speed = 0; } } if (game.bossBullets) { for (var i = 0; i < game.bossBullets.length; i++) { if (game.bossBullets[i]) game.bossBullets[i].vx = 0, game.bossBullets[i].vy = 0; } } if (game.bossFires) { for (var i = 0; i < game.bossFires.length; i++) { if (game.bossFires[i]) game.bossFires[i].vx = 0, game.bossFires[i].vy = 0; } } } } // 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 = -20 - (typeof difficulty !== "undefined" ? (difficulty - 1) * 2.2 : 0);
self.vy = (Math.random() - 0.5) * (3.5 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0));
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 = -24 - (typeof difficulty !== "undefined" ? (difficulty - 1) * 1.7 : 0); // 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 = -22 - (typeof difficulty !== "undefined" ? (difficulty - 1) * 2.0 : 0);
self.vy = (Math.random() - 0.5) * (5 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0));
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 = 10 + (typeof difficulty !== "undefined" ? (difficulty - 1) * 1.7 : 0) + Math.random() * 4.5;
self.vx = -baseSpeed;
self.vy = (Math.random() - 0.5) * (4.5 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0));
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: use selected asset if set, otherwise default to 'playerShip'
var assetId = typeof game !== "undefined" && game.selectedShipAssetId ? game.selectedShipAssetId : 'playerShip';
var shipAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Asset will be created as: ellipse, width: 140, height: 100, color: 0x3a9cff
shipAsset.width = 140;
shipAsset.height = 100;
// playership2 ve playership3 için kendi görseli kullanılsın, renk override etme
if (assetId === "playership2" || assetId === "playership3") {
// playership2 ve playership3'ün kendi görseli kullanılsın, renk override etme
} else {
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 = 18 + (typeof difficulty !== "undefined" ? (difficulty - 1) * 1.7 : 0) + Math.random() * 7;
self.vx = -speed;
self.vy = (Math.random() - 0.5) * (4 + (typeof difficulty !== "undefined" ? difficulty * 0.5 : 0)); // daha fazla 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
****/
// Yıldızlar: Parallax ve hafif dönen yıldızlar
// Galaksi arka planı kaldırıldı
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 = "";
// --- 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ı - made in TE";
}
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);
// 1. slot ise playership görselini ortala ve sığdır
if (row === 0 && col === 0) {
// Playership assetini tekrar kullanılabilir şekilde oluştur
if (!modalContainer._playershipAsset) {
var psMargin = 0.07 * slotSize;
var psSize = slotSize - 2 * psMargin;
var ps = LK.getAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: slotY,
width: psSize,
height: psSize
});
ps.alpha = 1;
modalContainer._playershipAsset = ps;
} else {
// Varsa mevcut asseti yeni konuma taşı
var ps = modalContainer._playershipAsset;
ps.x = slotX;
ps.y = slotY;
ps.width = slotSize - 2 * (0.07 * slotSize);
ps.height = slotSize - 2 * (0.07 * slotSize);
ps.alpha = 1;
}
modalContainer.addChild(ps);
}
// 2. slot ise playership2 görselini ortala ve sığdır
if (row === 0 && col === 1) {
// 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);
}
// 3. slot ise playership3 görselini ortala ve sığdır
if (row === 0 && col === 2) {
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 = [0, 100, 0]; // 1. slot ücretsiz, 2. slot 100 elmas, 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();
}
});
// Satın al butonunu kaldır, yerine kullan butonu ekle
if (btnRef && btnRef.parent) {
var parent = btnRef.parent;
var btnX = btnRef.x;
var btnY = btnRef.y;
var btnW = btnRef.width;
var btnH = btnRef.height;
// Fiyat etiketini kaldır
for (var ci = 0; ci < parent.children.length; ci++) {
var child = parent.children[ci];
if (child && child instanceof Text2 && child.text && (child.text.indexOf("+") !== -1 || child.text === price + "")) {
child.destroy();
// parent.children.splice(ci, 1); // Gerek yok, destroy yeterli
}
}
// Satın al butonunu kaldır
btnRef.destroy();
// "Kullan" butonu ekle
var useBtn = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: btnX,
y: btnY,
width: btnW,
height: btnH
});
// Hangi slotun hangi gemiye ait olduğunu belirle
var shipName = "";
if (col === 0) {
shipName = "playerShip";
} else if (col === 1) {
shipName = "playership2";
} else if (col === 2) {
shipName = "playership3";
} else {
shipName = "";
}
// Seçili gemiyle karşılaştır, aktifse butonu pasif yap
var isSelected = (game.selectedShipAssetId ? game.selectedShipAssetId : "playerShip") === shipName;
if (isSelected) {
useBtn.alpha = 0.45;
useBtn.color = 0x888888;
useBtn.interactive = false;
} else {
useBtn.alpha = 0.92;
useBtn.color = 0x7cbb37;
useBtn.interactive = true;
useBtn.defaultAlpha = useBtn.alpha;
useBtn.down = function (btnRef) {
return function (x, y, obj) {
btnRef.alpha = 0.65;
tween(btnRef, {
alpha: btnRef.defaultAlpha
}, {
duration: 120
});
var usedText = new Text2("Kullanıldı!", {
size: 36,
fill: 0x3a9cff
});
usedText.anchor.set(0.5, 0.5);
usedText.x = btnRef.x;
usedText.y = btnRef.y - 48;
modalContainer.addChild(usedText);
tween(usedText, {
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
usedText.destroy();
}
});
// --- Aktif gemiyi değiştir ---
// shipName'i kullanarak ilgili gemiyi aktif et
var newShipAssetId = shipName && typeof shipName === "string" && shipName.length > 0 ? shipName : "playerShip";
game.selectedShipAssetId = newShipAssetId;
// Eski gemiyi yok et
if (typeof playerShip !== "undefined" && playerShip && playerShip.parent) {
playerShip.destroy();
}
// Yeni gemiyi oluştur ve ekle
playerShip = new PlayerShip();
// Gemiyi uygun pozisyona yerleştir
playerShip.x = 350;
playerShip.y = 2732 / 2;
game.addChild(playerShip);
// Sağlık barı ve diğer göstergeleri güncelle
// Seçilen gemiye göre max health güncelle
if (game.selectedShipAssetId === "playership2") {
playerMaxHealth = 15;
} else if (game.selectedShipAssetId === "playership3") {
playerMaxHealth = 20;
} else {
playerMaxHealth = 10;
}
setPlayerHealth(playerMaxHealth);
updateCanBar();
updatePlayershipCanBar();
// Mağaza slotlarındaki tüm "Kullan" butonlarını güncelle (aktif/pasif)
if (parent && parent.children) {
for (var ci = 0; ci < parent.children.length; ci++) {
var child = parent.children[ci];
if (child && child !== btnRef && child.down && typeof child.interactive !== "undefined") {
// Sadece diğer "Kullan" butonlarını pasif yap
child.alpha = 0.45;
child.color = 0x888888;
child.interactive = false;
}
}
// Seçilen butonu aktif yap
btnRef.alpha = 0.45;
btnRef.color = 0x888888;
btnRef.interactive = false;
}
};
}(useBtn);
}
parent.addChild(useBtn);
// "Kullan" butonu yazısı
var useBtnLabel = "";
if (shipName === "playerShip") {
useBtnLabel = "playership Kullan";
} else if (shipName === "playership2") {
useBtnLabel = "playership2 Kullan";
} else if (shipName === "playership3") {
useBtnLabel = "playership3 Kullan";
} else {
useBtnLabel = "Kullan";
}
var useBtnText = new Text2(useBtnLabel, {
size: 32,
fill: "#fff"
});
useBtnText.anchor.set(0.5, 0.5);
useBtnText.x = useBtn.x;
useBtnText.y = useBtn.y;
useBtnText.interactive = !isSelected;
useBtnText.down = function (btnRef) {
return function (x, y, obj) {
if (btnRef && btnRef.down) btnRef.down(x, y, obj);
};
}(useBtn);
parent.addChild(useBtnText);
}
};
}(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 oyunda görünmesin, sadece bossDiamondObj ile elmas verilsin
if (diamondObj) {
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
if (typeof game !== "undefined" && game.selectedShipAssetId === "playership2") {
playerMaxHealth = 15; // playership2 için sağlık 15 olsun
} else if (typeof game !== "undefined" && game.selectedShipAssetId === "playership3") {
playerMaxHealth = 20; // playership3 için sağlık 20 olsun
}
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 = 2; // Başlangıç zorluğu 2 olsun
var spawnInterval = 80; // ticks, daha hızlı başlasın
var lastSpawnTick = 0;
shootInterval = 180; // daha hızlı 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 (storage'dan yükle, yoksa 0)
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 + "");
// Elmas sayısını storage'a kaydet
storage.diamondCount = 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
// Ava: Skor panelinin kaybolmasını engellemek için her frame tekrar ekle
if (!game._scoreDiamondContainerCheckAdded) {
game._scoreDiamondContainerCheckAdded = true;
game.updateScoreDiamondContainerVisibility = function () {
if (!scoreDiamondContainer.parent) {
LK.gui.top.addChild(scoreDiamondContainer);
}
scoreDiamondContainer.visible = true;
scoreTxt.visible = true;
diamondCounterContainer.visible = true;
};
// Her frame kontrol et
var _scoreDiamondContainerInterval = LK.setInterval(function () {
if (typeof game.updateScoreDiamondContainerVisibility === "function") {
game.updateScoreDiamondContainerVisibility();
}
}, 200);
}
// 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 && typeof game.enemiesKilled !== "undefined" && game.enemiesKilled >= 20) {
// Only allow one enemyship2 on screen at a time (use ._isEnemyship2 flag for reliability)
var hasEnemyship2 = false;
for (var i = 0; i < spaceObjects.length; i++) {
var so = spaceObjects[i];
if (so && so._isEnemyship2) {
hasEnemyship2 = true;
break;
}
}
if (hasEnemyship2) {
// Do not spawn another enemyship2
return;
}
// enemyship2 (yeni düşman tipi)
obj = new Container();
obj._isEnemyship2 = true; // Reliable type flag for enemyship2
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-20 arası, her 3 puanda bir artar, maksimum 20 (daha hızlı ve daha yüksek artış)
var newDifficulty = 1 + Math.floor(score / 3);
if (newDifficulty > 20) newDifficulty = 20;
if (newDifficulty > difficulty) {
difficulty = newDifficulty;
}
// spawnInterval: Kolayda yavaş (60), zorda çok hızlı (4)
// 1. zorlukta 60, 20. zorlukta 4
spawnInterval = Math.round(60 - (difficulty - 1) * 2.9);
if (spawnInterval < 4) spawnInterval = 4;
// Mermi hızını ve ateş sıklığını zorlukla birlikte daha fazla artır
// shootInterval: 1. zorlukta 120, 20. zorlukta 12
shootInterval = Math.round(120 - (difficulty - 1) * 5.7);
if (shootInterval < 12) shootInterval = 12;
// 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._isEnemyship2) {
// enemyship2 ise 3 birim hasar
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._isEnemyship2) {
// 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._isEnemyship2) {
scoreToAdd = 5;
}
// EnemyShip (eski tip) 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;
// --- Bossfire spiral ve dairesel atış kaldırıldı, sadece klasik yayılma atışı kaldı ---
if (!bossFireJustFired && LK.ticks - game.lastBossFireTick > 480) {
// 8 saniye (60fps*8=480)
// Sadece klasik yayılma atışı
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: 80,
height: 80
});
bossFire.vx = -13;
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.lastBossFireTick = LK.ticks;
bossFireJustFired = true;
}
// Boss mermisi ateşle
if (!bossFireJustFired && LK.ticks - game.lastBossBulletTick > game.bossBulletCooldown) {
// --- GELİŞTİRİLMİŞ: Zigzag ve spiral boss mermileri ---
var slotCount = 5;
var slotOffsets = [];
var bossImgHeight = game.bossImg.height || 400;
var slotSpacing = bossImgHeight / (slotCount + 1);
for (var si = 0; si < slotCount; si++) {
var slotY = -bossImgHeight / 2 + slotSpacing * (si + 1);
slotOffsets.push({
y: slotY,
angle: 0
});
}
// Zigzag boss mermileri
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
});
// Zigzag için başlangıç fazı
bossBullet._zigzagPhase = Math.random() * Math.PI * 2;
bossBullet._zigzagSpeed = 2.5 + Math.random() * 1.5;
bossBullet._zigzagAmp = 38 + Math.random() * 22;
var speed = 10;
bossBullet.vx = -speed;
bossBullet.vy = 0;
bossBullet._baseY = bossBullet.y;
bossBullet._bornTick = LK.ticks;
bossBullet.update = function (bullet) {
return function () {
bullet.x += bullet.vx;
// Zigzag hareket: y = baseY + amp * sin(frekans * t + faz)
var t = (LK.ticks - bullet._bornTick) / 12;
bullet.y = bullet._baseY + Math.sin(t * bullet._zigzagSpeed + bullet._zigzagPhase) * bullet._zigzagAmp;
};
}(bossBullet);
game.bossBullets.push(bossBullet);
game.addChild(bossBullet);
}
// Spiral boss mermileri (daha zor için)
if (game.bossHealth < game.bossMaxHealth * 0.5) {
var spiralCount = 8;
var spiralRadius = 0;
var spiralSpeed = 7;
for (var sp = 0; sp < spiralCount; sp++) {
var angle = Math.PI * 2 / spiralCount * sp + LK.ticks % 60 / 60 * Math.PI * 2;
var spiralBullet = LK.getAsset('bossmermi', {
anchorX: 0.5,
anchorY: 0.5,
x: game.bossImg.x - (game.bossImg.width || 400) / 2 - 40,
y: game.bossImg.y,
width: 40,
height: 40
});
spiralBullet._angle = angle;
spiralBullet._radius = spiralRadius;
spiralBullet._speed = spiralSpeed;
spiralBullet._bornTick = LK.ticks;
spiralBullet.update = function (bullet) {
return function () {
// Spiral hareket: açı artar, x ve y ona göre değişir
bullet._angle += 0.07;
bullet.x += Math.cos(bullet._angle) * bullet._speed - 6;
bullet.y += Math.sin(bullet._angle) * bullet._speed;
};
}(spiralBullet);
game.bossBullets.push(spiralBullet);
game.addChild(spiralBullet);
}
}
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 - 8); // bossfire hasarı 8 (daha fazla)
}
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 - 6); // bossmermi hasarı 6 (daha fazla)
}
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;
// --- GELİŞTİRİLMİŞ: Boss hareketine ileri-geri ve yukarı-aşağı dalga ekle ---
var t = LK.ticks / 60; // yavaş hareket için
var bossTargetX = bossCenterX + Math.cos(t) * bossMoveRadiusX + Math.sin(t * 2.2) * 60;
var bossTargetY = bossCenterY + Math.sin(t * 0.8) * bossMoveRadiusY + Math.cos(t * 1.7) * 40;
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 = 200; // Boss'un toplam canı artık 200
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ÇİŞİ ---
// Boss faz 2 iptal: Boss her zaman faz 1'de kalacak, faz geçişi ve faz 2 saldırı güçlendirmeleri kaldırıldı.
if (typeof game.bossPhase === "undefined") {
game.bossPhase = 1;
}
// 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Ü: Portalı aktif et ---
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;
}
}
});
}
return;
// Elmas sadece skor panelinde gösterilecek, oyun alanında diamond objesi spawn edilmez.
// --- 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 - 10); // boss çarpışma hasarı 10 (daha fazla)
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
// --- Ava: Ekrana 'continius' yazısı ekle ---
var continiusText = new Text2("continius", {
size: 140,
fill: 0xFFE066,
font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'",
maxWidth: 1800
});
continiusText.anchor.set(0.5, 0.5);
continiusText.x = 2048 / 2;
continiusText.y = 2732 / 2;
continiusText.alpha = 0;
game.addChild(continiusText);
tween(continiusText, {
alpha: 1
}, {
duration: 800,
onFinish: function onFinish() {
// Birkaç saniye sonra yavaşça kaybolsun
tween(continiusText, {
alpha: 0
}, {
duration: 1800,
delay: 2200,
onFinish: function onFinish() {
if (continiusText && continiusText.parent) continiusText.destroy();
}
});
}
});
}
});
game.portal.destroy();
game.portal = null;
}
}
});
}
game.portal.lastWasIntersecting = portalIntersect;
}
}
// --- Black Hole (Kara Delik) Mekaniği ---
// Kara delik objesi ve spawn kontrolü
if (typeof blackHoleObj === "undefined") blackHoleObj = null;
if (typeof lastBlackHoleSpawnTick === "undefined") lastBlackHoleSpawnTick = -10000;
var blackHoleSpawnCooldown = 4200 + Math.floor(Math.random() * 1800); // 70-100 sn arası
if (!blackHoleObj && LK.ticks - lastBlackHoleSpawnTick > blackHoleSpawnCooldown) {
// %5 olasılıkla kara delik spawn et (çok nadir)
if (Math.random() < 0.05) {
blackHoleObj = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 400 + Math.random() * 400 - 200,
y: 400 + Math.random() * (2732 - 800),
width: 180,
height: 180
});
blackHoleObj.alpha = 0.7;
blackHoleObj.color = 0x222233;
blackHoleObj.vx = -2.5 - Math.random() * 2.5;
blackHoleObj.vy = (Math.random() - 0.5) * 2.0;
blackHoleObj.radius = 90;
blackHoleObj._pullStrength = 0.7 + Math.random() * 0.5;
blackHoleObj._lifetime = 900 + Math.floor(Math.random() * 600); // 15-25 sn ekranda kalır
blackHoleObj._spawnTick = LK.ticks;
blackHoleObj.update = function () {
// Hareket
blackHoleObj.x += blackHoleObj.vx;
blackHoleObj.y += blackHoleObj.vy;
// Ekran dışına çıkarsa yok et
if (blackHoleObj.x < -200 || blackHoleObj.x > 2048 + 200 || blackHoleObj.y < -200 || blackHoleObj.y > 2732 + 200) {
blackHoleObj.destroy();
blackHoleObj = null;
return;
}
// Süresi dolduysa yok et
if (LK.ticks - blackHoleObj._spawnTick > blackHoleObj._lifetime) {
// Fade out
tween(blackHoleObj, {
alpha: 0
}, {
duration: 600,
onFinish: function onFinish() {
if (blackHoleObj && blackHoleObj.parent) blackHoleObj.destroy();
blackHoleObj = null;
}
});
return;
}
// Kara delik çekim etkisi: yakınındaki objeleri kendine çeker
var pullRadius = 420;
// Uzay cisimleri
for (var i = 0; i < spaceObjects.length; i++) {
var so = spaceObjects[i];
if (!so || !so.x || !so.y) continue;
var dx = blackHoleObj.x - so.x;
var dy = blackHoleObj.y - so.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < pullRadius && dist > 1) {
var pull = blackHoleObj._pullStrength * (1 - dist / pullRadius);
so.vx += dx / dist * pull;
so.vy += dy / dist * pull;
}
}
// Mermiler
for (var i = 0; i < bullets.length; i++) {
var b = bullets[i];
if (!b || !b.x || !b.y) continue;
var dx = blackHoleObj.x - b.x;
var dy = blackHoleObj.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < pullRadius && dist > 1) {
var pull = blackHoleObj._pullStrength * 0.7 * (1 - dist / pullRadius);
b.speed *= 0.98; // Kara delik yakınında mermiler yavaşlar
b.x += dx / dist * pull * 0.7;
b.y += dy / dist * pull * 0.7;
}
}
// Oyuncu gemisi
if (playerShip && playerShip.x && playerShip.y) {
var dx = blackHoleObj.x - playerShip.x;
var dy = blackHoleObj.y - playerShip.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < pullRadius && dist > 1) {
var pull = blackHoleObj._pullStrength * 0.5 * (1 - dist / pullRadius);
// Sürüklenmiyorsa gemiyi hafifçe çeksin
if (!dragging && !playerShip._autoMovingToPortal) {
playerShip.x += dx / dist * pull;
playerShip.y += dy / dist * pull;
}
}
// Kara deliğe çok yaklaşırsa (merkezine), anında yok olma
if (dist < blackHoleObj.radius + (playerShip.radius || 70) - 10) {
// Patlama efekti
var bhExpl = 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(bhExpl);
tween(bhExpl, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
bhExpl.destroy();
}
});
setPlayerHealth(0);
if (playerHealth <= 0) {
LK.showGameOver();
return;
}
}
}
// Hafif nabız efekti
var t = LK.ticks % 60 / 60;
var scale = 1.0 + 0.08 * Math.sin(t * Math.PI * 2);
blackHoleObj.scaleX = scale;
blackHoleObj.scaleY = scale;
};
game.addChild(blackHoleObj);
lastBlackHoleSpawnTick = LK.ticks;
} else {
// spawn denemesi başarısızsa tekrar denemek için tick'i güncelleme
lastBlackHoleSpawnTick = LK.ticks;
}
}
// Kara delik güncellemesi
if (blackHoleObj && blackHoleObj.update) {
blackHoleObj.update();
}
// --- 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;
}
}
// --- Time Freeze Power-up (Zamanı Dondur) ---
// Sadece bir tane ekranda olabilir
if (typeof timeFreezeObj === "undefined") timeFreezeObj = null;
if (typeof lastTimeFreezeSpawnTick === "undefined") lastTimeFreezeSpawnTick = -10000;
var timeFreezeSpawnCooldown = 2400 + Math.floor(Math.random() * 1200); // 40-60 sn arası
if (!timeFreezeObj && LK.ticks - lastTimeFreezeSpawnTick > timeFreezeSpawnCooldown) {
// %08 olasılıkla zaman dondur spawn et
if (Math.random() < 0.08) {
timeFreezeObj = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 400 + Math.random() * 400 - 200,
y: 400 + Math.random() * (2732 - 800),
width: 120,
height: 120
});
timeFreezeObj.alpha = 0.92;
timeFreezeObj.color = 0x66e0ff;
timeFreezeObj.vx = -3 - Math.random() * 2.5;
timeFreezeObj.vy = (Math.random() - 0.5) * 2.0;
timeFreezeObj.radius = 60;
timeFreezeObj._lifetime = 600 + Math.floor(Math.random() * 400); // 10-16 sn ekranda kalır
timeFreezeObj._spawnTick = LK.ticks;
timeFreezeObj.update = function () {
timeFreezeObj.x += timeFreezeObj.vx;
timeFreezeObj.y += timeFreezeObj.vy;
// Ekran dışına çıkarsa yok et
if (timeFreezeObj.x < -150 || timeFreezeObj.x > 2048 + 150 || timeFreezeObj.y < -150 || timeFreezeObj.y > 2732 + 150) {
timeFreezeObj.destroy();
timeFreezeObj = null;
return;
}
// Süresi dolduysa yok et
if (LK.ticks - timeFreezeObj._spawnTick > timeFreezeObj._lifetime) {
tween(timeFreezeObj, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
if (timeFreezeObj && timeFreezeObj.parent) timeFreezeObj.destroy();
timeFreezeObj = null;
}
});
return;
}
// Oyuncu toplarsa zamanı dondur
if (playerShip && isCircleHit(timeFreezeObj, playerShip)) {
// Efekt: patlama
var tfEffect = LK.getAsset('patlamaeffekt', {
anchorX: 0.5,
anchorY: 0.5,
x: timeFreezeObj.x,
y: timeFreezeObj.y,
width: 120,
height: 120
});
tfEffect.alpha = 0.7;
game.addChild(tfEffect);
tween(tfEffect, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 400,
onFinish: function onFinish() {
tfEffect.destroy();
}
});
// Zamanı dondur: tüm düşmanlar ve mermiler 3 saniye boyunca hareket etmesin
game._timeFreezeActive = true;
game._timeFreezeEndTick = LK.ticks + 180; // 3 saniye
// Görsel: ekranın üstünde "Zaman Dondu!" yazısı
var freezeText = new Text2("Zaman Dondu!", {
size: 110,
fill: 0x66e0ff,
font: "'GillSans-Bold', 'Segoe UI', 'Arial', 'Tahoma'",
maxWidth: 1800
});
freezeText.anchor.set(0.5, 0.5);
freezeText.x = 2048 / 2;
freezeText.y = 2732 / 2 - 300;
freezeText.alpha = 0;
game.addChild(freezeText);
tween(freezeText, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
tween(freezeText, {
alpha: 0
}, {
duration: 800,
delay: 1800,
onFinish: function onFinish() {
if (freezeText && freezeText.parent) freezeText.destroy();
}
});
}
});
timeFreezeObj.destroy();
timeFreezeObj = null;
}
// Hafif parıltı efekti
var t = LK.ticks % 60 / 60;
var scale = 1.0 + 0.12 * Math.sin(t * Math.PI * 2);
timeFreezeObj.scaleX = scale;
timeFreezeObj.scaleY = scale;
};
game.addChild(timeFreezeObj);
lastTimeFreezeSpawnTick = LK.ticks;
} else {
lastTimeFreezeSpawnTick = LK.ticks;
}
}
// Time freeze güncellemesi
if (timeFreezeObj && timeFreezeObj.update) {
timeFreezeObj.update();
}
// Time freeze aktifse, düşmanlar ve mermiler hareket etmesin
if (game._timeFreezeActive) {
if (LK.ticks >= game._timeFreezeEndTick) {
game._timeFreezeActive = false;
} else {
// Düşmanlar ve mermiler update fonksiyonlarını atla
for (var i = 0; i < spaceObjects.length; i++) {
if (spaceObjects[i]) spaceObjects[i].vx = 0, spaceObjects[i].vy = 0;
}
if (game.enemyBullets) {
for (var i = 0; i < game.enemyBullets.length; i++) {
if (game.enemyBullets[i]) game.enemyBullets[i].speed = 0;
}
}
if (game.bossBullets) {
for (var i = 0; i < game.bossBullets.length; i++) {
if (game.bossBullets[i]) game.bossBullets[i].vx = 0, game.bossBullets[i].vy = 0;
}
}
if (game.bossFires) {
for (var i = 0; i < game.bossFires.length; i++) {
if (game.bossFires[i]) game.bossFires[i].vx = 0, game.bossFires[i].vy = 0;
}
}
}
}
// 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