/****
* 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
****/
// Galaksi arka planı kaldırıldı
// Yıldızlar: Parallax ve hafif dönen yıldızlar
var starBgCount = 90;
var stars = [];
var starBgContainer = new Container();
for (var i = 0; i < starBgCount; i++) {
var starSize = 2 + Math.random() * 4;
var star = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: Math.random() * 2732,
width: starSize,
height: starSize
});
// Farklı parlaklıklar
star.alpha = 0.3 + Math.random() * 0.7;
// Farklı hızlar (parallax)
star._vx = 0.7 + Math.random() * 1.2;
// Hafif döndürme efekti
star._rotSpeed = (Math.random() - 0.5) * 0.01;
stars.push(star);
starBgContainer.addChild(star);
}
game.addChild(starBgContainer); // Yıldız arka planı ekle (addChildAt yerine addChild ile, out of bounds hatasını önler)
// --- BAŞLANGIÇ MENÜSÜ ---
var startMenuContainer = new Container();
// Oyun başı intro sahnesi kaldırıldı, menü doğrudan gösteriliyor
if (!startMenuContainer.parent) {
startMenuContainer.alpha = 1;
startMenuContainer.scaleX = 1;
startMenuContainer.scaleY = 1;
game.addChild(startMenuContainer);
}
// Menü renklerini dinamik olarak yönetmek için global değişkenler
var menuBgColor = 0x181c2b;
var menuButtonColors = [0x3a9cff, 0x4e5d94, 0x7cbb37, 0xf7b32b];
var menuWidth = 1000;
var menuHeight = 1100;
// Menü arka planına renkli kutu ekle (görsel yerine)
var startMenuBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: menuHeight / 2,
width: menuWidth,
height: menuHeight
});
startMenuBg.alpha = 0.0; // Tamamen şeffaf yap
startMenuBg.color = menuBgColor;
startMenuContainer.addChild(startMenuBg);
// Menü arka planına border efekti kaldırıldı (menu image ile uyumlu)
// Başlık ve alt başlık
var titleText = new Text2("UZAY MACERASI", {
size: 120,
fill: 0xFFE066
});
titleText.anchor.set(0.5, 0.5);
titleText.x = menuWidth / 2;
titleText.y = 140;
startMenuContainer.addChild(titleText);
// Subtitle text removed as requested
// Dinamik butonlar
var menuButtons = [{
label: "Yeni Oyun",
key: "start",
color: 0x3a9cff
}, {
label: "Mağaza",
key: "options",
color: 0x4e5d94
}, {
label: "Rekorlar",
key: "scores",
color: 0x7cbb37
}, {
label: "Hakkında",
key: "about",
color: 0xf7b32b
}];
var buttonHeight = 140;
var buttonWidth = 600;
var buttonSpacing = 48;
var firstBtnY = 400;
var btnBgList = [];
var btnTextList = [];
for (var i = 0; i < menuButtons.length; i++) {
var btnY = firstBtnY + i * (buttonHeight + buttonSpacing);
// Butonun arka planı (hafif gölgeli, modern)
var btnBgShadow = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2 + 8,
y: btnY + 10,
width: buttonWidth + 24,
height: buttonHeight + 18
});
btnBgShadow.alpha = 0.18;
btnBgShadow.color = 0x000000;
startMenuContainer.addChild(btnBgShadow);
var btnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: btnY,
width: buttonWidth,
height: buttonHeight
});
btnBg.alpha = 0.92;
btnBg.color = menuButtonColors[i % menuButtonColors.length];
btnBg.menuKey = menuButtons[i].key;
btnBg.buttonIndex = i;
btnBg.interactive = true; // Buton tıklanabilir olsun
btnBg.defaultAlpha = btnBg.alpha; // Tıklama efekti için orijinal alpha
btnBg.down = function (btn) {
return function (x, y, obj) {
// Tıklama efekti: sadece bu buton için kısa bir görsel geri bildirim uygula
btn.alpha = 0.65;
tween(btn, {
alpha: btn.defaultAlpha
}, {
duration: 120
});
// Her butonun kendi işlevi
if (btn.menuKey === "start") {
// Menü animasyonla kaybolsun ve oyun başlasın
tween(startMenuContainer, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 350,
onFinish: function onFinish() {
if (startMenuContainer && startMenuContainer.parent) startMenuContainer.destroy();
// Oyun başladığında süreyi 3 dakikaya (180 saniye) sıfırla
timeLeft = gameDuration;
updateTimerDisplay();
gameStarted = true;
}
});
} else {
// Her menü butonu için yeni bir ekran (modal) aç
// Ana menü ekranını gizle
if (startMenuContainer && startMenuContainer.parent) {
startMenuContainer.visible = false;
}
var modalW = 1200;
var modalH = 1000;
var modalContainer = new Container();
var modalBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: modalH / 2,
width: modalW,
height: modalH
});
modalBg.alpha = 0.0; // Tamamen şeffaf yap
modalBg.color = 0x181c2b;
modalContainer.addChild(modalBg);
var modalTitle = "";
var modalContent = "";
if (btn.menuKey === "options") {
modalTitle = "Mağaza";
modalContent = "";
// Satın alınabilir ürünler
var storeProducts = [];
// Ürünleri listele ve satın al butonları ekle
var productBtnH = 110;
var productBtnW = 600;
var productBtnSpacing = 24;
var firstProductY = 260;
for (var p = 0; p < storeProducts.length; p++) {
var prod = storeProducts[p];
var prodY = firstProductY + p * (productBtnH + productBtnSpacing);
// Ürün kutusu
var prodBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: prodY,
width: productBtnW,
height: productBtnH
});
prodBg.alpha = 0.0; // Tamamen şeffaf yap
prodBg.color = 0x232a3d;
modalContainer.addChild(prodBg);
// Ürün açıklaması (isim kaldırıldığı için üstte hizalanacak)
var prodDesc = new Text2(prod.desc, {
size: 36,
fill: 0xB0E0FF,
maxWidth: productBtnW - 220
});
// Açıklamayı butonun üstüne hizala
prodDesc.anchor.set(0, 1);
prodDesc.x = modalW / 2 - productBtnW / 2 + 32;
prodDesc.y = prodY - productBtnH / 2 + 18;
modalContainer.addChild(prodDesc);
// Fiyat etiketi
var priceTag = new Text2(prod.price + " 💎", {
size: 44,
fill: 0xFFE066
});
priceTag.anchor.set(1, 0.5);
priceTag.x = modalW / 2 + productBtnW / 2 - 120;
priceTag.y = prodY;
modalContainer.addChild(priceTag);
// Satın al butonu
var buyBtn = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2 + productBtnW / 2 - 60,
y: prodY,
width: 100,
height: 80
});
buyBtn.alpha = 0.85;
buyBtn.color = 0x3a9cff; // Mavi ton, kırmızı arka plan kaldırıldı
buyBtn.interactive = true;
buyBtn.down = function (prod, buyBtnRef) {
return function (x, y, obj) {
// Satın alma işlemi (örnek: elmas bakiyesi yok, sadece görsel feedback)
buyBtnRef.alpha = 0.65;
tween(buyBtnRef, {
alpha: 0.85
}, {
duration: 120
});
// Satın alma bildirimi
var boughtText = new Text2("Satın alındı!", {
size: 44,
fill: 0x7CBB37
});
boughtText.anchor.set(0.5, 0.5);
boughtText.x = buyBtnRef.x;
boughtText.y = buyBtnRef.y - 60;
modalContainer.addChild(boughtText);
tween(boughtText, {
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
boughtText.destroy();
}
});
};
}(prod, buyBtn);
modalContainer.addChild(buyBtn);
// Satın al butonu yazısı
var buyBtnText = new Text2("Satın Al", {
size: 36,
fill: "#fff"
});
buyBtnText.anchor.set(0.5, 0.5);
buyBtnText.x = buyBtn.x;
buyBtnText.y = buyBtn.y;
buyBtnText.interactive = true;
buyBtnText.down = function (buyBtnRef) {
return function (x, y, obj) {
if (buyBtnRef && buyBtnRef.down) buyBtnRef.down(x, y, obj);
};
}(buyBtn);
modalContainer.addChild(buyBtnText);
}
} else if (btn.menuKey === "scores") {
modalTitle = "";
// --- High Scores Modal Content ---
var scoresArr = getHighScores();
if (scoresArr.length === 0) {
modalContent = "Henüz rekor yok!";
} else {
modalContent = "En Yüksek 5 Skor:\n";
for (var s = 0; s < scoresArr.length; s++) {
modalContent += s + 1 + ". " + scoresArr[s] + "\n";
}
}
} else if (btn.menuKey === "about") {
modalTitle = "Hakkında";
modalContent = "Uzay Macerası - FRVR.Ava.Combo[POGAAS].v1.0";
}
var modalTitleText = new Text2(modalTitle, {
size: 100,
fill: 0xFFE066,
maxWidth: modalW - 80 // kutu kenarından taşmasın
});
modalTitleText.anchor.set(0.5, 0.5);
modalTitleText.x = modalW / 2;
modalTitleText.y = 120;
modalContainer.addChild(modalTitleText);
// --- 3x3 Kare Slotlar: Mağaza başlığı ile kapat tuşu arasına ---
// Sadece mağaza menüsünde slotlar görünsün
if (btn.menuKey === "options") {
// Kare slotlar için parametreler
var slotSize = 280; // Daha büyük slotlar
var slotSpacing = 64; // Slotlar arası biraz daha fazla boşluk
var slotsPerRow = 3;
var slotsPerCol = 1; // Artık sadece 1 satır olacak
// Slotların başlık ile kapat tuşu arasında ortalanması ve kapat tuşu ile çakışmaması için Y konumunu ayarla
// Kapat tuşu modalın en altında, slotlar başlığın hemen altından başlasın ve slotların altı ile kapat tuşu arasında yeterli boşluk kalsın
var slotsTotalWidth = slotsPerRow * slotSize + (slotsPerRow - 1) * slotSpacing;
var slotsTotalHeight = slotSize; // Sadece 1 satır
var closeBtnH = 100;
var closeBtnY = modalH - closeBtnH / 2 - 24;
// Slotları modalın ortasına dikeyde ortala, başlık ile kapat tuşu arasında
var availableHeight = closeBtnY - (modalTitleText.y + 120) - 40;
var slotsStartY = modalTitleText.y + 120 + Math.max(0, (availableHeight - slotsTotalHeight) / 2);
// Slotları yatayda tam merkeze hizala
var slotsStartX = modalW / 2 - slotsTotalWidth / 2 + slotSize / 2;
var slotList = [];
for (var row = 0; row < slotsPerCol; row++) {
for (var col = 0; col < slotsPerRow; col++) {
var slotX = slotsStartX + col * (slotSize + slotSpacing);
var slotY = slotsStartY + row * (slotSize + slotSpacing);
var slot = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: slotY,
width: slotSize,
height: slotSize
});
slot.alpha = 0.18;
slot.color = 0xB0E0FF;
modalContainer.addChild(slot);
slotList.push(slot);
// 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
****/
// Galaksi arka planı kaldırıldı
// Yıldızlar: Parallax ve hafif dönen yıldızlar
var starBgCount = 90;
var stars = [];
var starBgContainer = new Container();
for (var i = 0; i < starBgCount; i++) {
var starSize = 2 + Math.random() * 4;
var star = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: Math.random() * 2048,
y: Math.random() * 2732,
width: starSize,
height: starSize
});
// Farklı parlaklıklar
star.alpha = 0.3 + Math.random() * 0.7;
// Farklı hızlar (parallax)
star._vx = 0.7 + Math.random() * 1.2;
// Hafif döndürme efekti
star._rotSpeed = (Math.random() - 0.5) * 0.01;
stars.push(star);
starBgContainer.addChild(star);
}
game.addChild(starBgContainer); // Yıldız arka planı ekle (addChildAt yerine addChild ile, out of bounds hatasını önler)
// --- BAŞLANGIÇ MENÜSÜ ---
var startMenuContainer = new Container();
// Oyun başı intro sahnesi kaldırıldı, menü doğrudan gösteriliyor
if (!startMenuContainer.parent) {
startMenuContainer.alpha = 1;
startMenuContainer.scaleX = 1;
startMenuContainer.scaleY = 1;
game.addChild(startMenuContainer);
}
// Menü renklerini dinamik olarak yönetmek için global değişkenler
var menuBgColor = 0x181c2b;
var menuButtonColors = [0x3a9cff, 0x4e5d94, 0x7cbb37, 0xf7b32b];
var menuWidth = 1000;
var menuHeight = 1100;
// Menü arka planına renkli kutu ekle (görsel yerine)
var startMenuBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: menuHeight / 2,
width: menuWidth,
height: menuHeight
});
startMenuBg.alpha = 0.0; // Tamamen şeffaf yap
startMenuBg.color = menuBgColor;
startMenuContainer.addChild(startMenuBg);
// Menü arka planına border efekti kaldırıldı (menu image ile uyumlu)
// Başlık ve alt başlık
var titleText = new Text2("UZAY MACERASI", {
size: 120,
fill: 0xFFE066
});
titleText.anchor.set(0.5, 0.5);
titleText.x = menuWidth / 2;
titleText.y = 140;
startMenuContainer.addChild(titleText);
// Subtitle text removed as requested
// Dinamik butonlar
var menuButtons = [{
label: "Yeni Oyun",
key: "start",
color: 0x3a9cff
}, {
label: "Mağaza",
key: "options",
color: 0x4e5d94
}, {
label: "Rekorlar",
key: "scores",
color: 0x7cbb37
}, {
label: "Hakkında",
key: "about",
color: 0xf7b32b
}];
var buttonHeight = 140;
var buttonWidth = 600;
var buttonSpacing = 48;
var firstBtnY = 400;
var btnBgList = [];
var btnTextList = [];
for (var i = 0; i < menuButtons.length; i++) {
var btnY = firstBtnY + i * (buttonHeight + buttonSpacing);
// Butonun arka planı (hafif gölgeli, modern)
var btnBgShadow = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2 + 8,
y: btnY + 10,
width: buttonWidth + 24,
height: buttonHeight + 18
});
btnBgShadow.alpha = 0.18;
btnBgShadow.color = 0x000000;
startMenuContainer.addChild(btnBgShadow);
var btnBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: menuWidth / 2,
y: btnY,
width: buttonWidth,
height: buttonHeight
});
btnBg.alpha = 0.92;
btnBg.color = menuButtonColors[i % menuButtonColors.length];
btnBg.menuKey = menuButtons[i].key;
btnBg.buttonIndex = i;
btnBg.interactive = true; // Buton tıklanabilir olsun
btnBg.defaultAlpha = btnBg.alpha; // Tıklama efekti için orijinal alpha
btnBg.down = function (btn) {
return function (x, y, obj) {
// Tıklama efekti: sadece bu buton için kısa bir görsel geri bildirim uygula
btn.alpha = 0.65;
tween(btn, {
alpha: btn.defaultAlpha
}, {
duration: 120
});
// Her butonun kendi işlevi
if (btn.menuKey === "start") {
// Menü animasyonla kaybolsun ve oyun başlasın
tween(startMenuContainer, {
alpha: 0,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 350,
onFinish: function onFinish() {
if (startMenuContainer && startMenuContainer.parent) startMenuContainer.destroy();
// Oyun başladığında süreyi 3 dakikaya (180 saniye) sıfırla
timeLeft = gameDuration;
updateTimerDisplay();
gameStarted = true;
}
});
} else {
// Her menü butonu için yeni bir ekran (modal) aç
// Ana menü ekranını gizle
if (startMenuContainer && startMenuContainer.parent) {
startMenuContainer.visible = false;
}
var modalW = 1200;
var modalH = 1000;
var modalContainer = new Container();
var modalBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: modalH / 2,
width: modalW,
height: modalH
});
modalBg.alpha = 0.0; // Tamamen şeffaf yap
modalBg.color = 0x181c2b;
modalContainer.addChild(modalBg);
var modalTitle = "";
var modalContent = "";
if (btn.menuKey === "options") {
modalTitle = "Mağaza";
modalContent = "";
// Satın alınabilir ürünler
var storeProducts = [];
// Ürünleri listele ve satın al butonları ekle
var productBtnH = 110;
var productBtnW = 600;
var productBtnSpacing = 24;
var firstProductY = 260;
for (var p = 0; p < storeProducts.length; p++) {
var prod = storeProducts[p];
var prodY = firstProductY + p * (productBtnH + productBtnSpacing);
// Ürün kutusu
var prodBg = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2,
y: prodY,
width: productBtnW,
height: productBtnH
});
prodBg.alpha = 0.0; // Tamamen şeffaf yap
prodBg.color = 0x232a3d;
modalContainer.addChild(prodBg);
// Ürün açıklaması (isim kaldırıldığı için üstte hizalanacak)
var prodDesc = new Text2(prod.desc, {
size: 36,
fill: 0xB0E0FF,
maxWidth: productBtnW - 220
});
// Açıklamayı butonun üstüne hizala
prodDesc.anchor.set(0, 1);
prodDesc.x = modalW / 2 - productBtnW / 2 + 32;
prodDesc.y = prodY - productBtnH / 2 + 18;
modalContainer.addChild(prodDesc);
// Fiyat etiketi
var priceTag = new Text2(prod.price + " 💎", {
size: 44,
fill: 0xFFE066
});
priceTag.anchor.set(1, 0.5);
priceTag.x = modalW / 2 + productBtnW / 2 - 120;
priceTag.y = prodY;
modalContainer.addChild(priceTag);
// Satın al butonu
var buyBtn = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: modalW / 2 + productBtnW / 2 - 60,
y: prodY,
width: 100,
height: 80
});
buyBtn.alpha = 0.85;
buyBtn.color = 0x3a9cff; // Mavi ton, kırmızı arka plan kaldırıldı
buyBtn.interactive = true;
buyBtn.down = function (prod, buyBtnRef) {
return function (x, y, obj) {
// Satın alma işlemi (örnek: elmas bakiyesi yok, sadece görsel feedback)
buyBtnRef.alpha = 0.65;
tween(buyBtnRef, {
alpha: 0.85
}, {
duration: 120
});
// Satın alma bildirimi
var boughtText = new Text2("Satın alındı!", {
size: 44,
fill: 0x7CBB37
});
boughtText.anchor.set(0.5, 0.5);
boughtText.x = buyBtnRef.x;
boughtText.y = buyBtnRef.y - 60;
modalContainer.addChild(boughtText);
tween(boughtText, {
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
boughtText.destroy();
}
});
};
}(prod, buyBtn);
modalContainer.addChild(buyBtn);
// Satın al butonu yazısı
var buyBtnText = new Text2("Satın Al", {
size: 36,
fill: "#fff"
});
buyBtnText.anchor.set(0.5, 0.5);
buyBtnText.x = buyBtn.x;
buyBtnText.y = buyBtn.y;
buyBtnText.interactive = true;
buyBtnText.down = function (buyBtnRef) {
return function (x, y, obj) {
if (buyBtnRef && buyBtnRef.down) buyBtnRef.down(x, y, obj);
};
}(buyBtn);
modalContainer.addChild(buyBtnText);
}
} else if (btn.menuKey === "scores") {
modalTitle = "";
// --- High Scores Modal Content ---
var scoresArr = getHighScores();
if (scoresArr.length === 0) {
modalContent = "Henüz rekor yok!";
} else {
modalContent = "En Yüksek 5 Skor:\n";
for (var s = 0; s < scoresArr.length; s++) {
modalContent += s + 1 + ". " + scoresArr[s] + "\n";
}
}
} else if (btn.menuKey === "about") {
modalTitle = "Hakkında";
modalContent = "Uzay Macerası - FRVR.Ava.Combo[POGAAS].v1.0";
}
var modalTitleText = new Text2(modalTitle, {
size: 100,
fill: 0xFFE066,
maxWidth: modalW - 80 // kutu kenarından taşmasın
});
modalTitleText.anchor.set(0.5, 0.5);
modalTitleText.x = modalW / 2;
modalTitleText.y = 120;
modalContainer.addChild(modalTitleText);
// --- 3x3 Kare Slotlar: Mağaza başlığı ile kapat tuşu arasına ---
// Sadece mağaza menüsünde slotlar görünsün
if (btn.menuKey === "options") {
// Kare slotlar için parametreler
var slotSize = 280; // Daha büyük slotlar
var slotSpacing = 64; // Slotlar arası biraz daha fazla boşluk
var slotsPerRow = 3;
var slotsPerCol = 1; // Artık sadece 1 satır olacak
// Slotların başlık ile kapat tuşu arasında ortalanması ve kapat tuşu ile çakışmaması için Y konumunu ayarla
// Kapat tuşu modalın en altında, slotlar başlığın hemen altından başlasın ve slotların altı ile kapat tuşu arasında yeterli boşluk kalsın
var slotsTotalWidth = slotsPerRow * slotSize + (slotsPerRow - 1) * slotSpacing;
var slotsTotalHeight = slotSize; // Sadece 1 satır
var closeBtnH = 100;
var closeBtnY = modalH - closeBtnH / 2 - 24;
// Slotları modalın ortasına dikeyde ortala, başlık ile kapat tuşu arasında
var availableHeight = closeBtnY - (modalTitleText.y + 120) - 40;
var slotsStartY = modalTitleText.y + 120 + Math.max(0, (availableHeight - slotsTotalHeight) / 2);
// Slotları yatayda tam merkeze hizala
var slotsStartX = modalW / 2 - slotsTotalWidth / 2 + slotSize / 2;
var slotList = [];
for (var row = 0; row < slotsPerCol; row++) {
for (var col = 0; col < slotsPerRow; col++) {
var slotX = slotsStartX + col * (slotSize + slotSpacing);
var slotY = slotsStartY + row * (slotSize + slotSpacing);
var slot = LK.getAsset('can', {
anchorX: 0.5,
anchorY: 0.5,
x: slotX,
y: slotY,
width: slotSize,
height: slotSize
});
slot.alpha = 0.18;
slot.color = 0xB0E0FF;
modalContainer.addChild(slot);
slotList.push(slot);
// 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
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