User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği veya mekaniği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak ve çeşitlilik katacak ayrıca otomasyon hale gelecek AdventureRPG katacak mekanik ve özellik ekle.
User prompt
Korsan altında bulunan ''savunma seviye'' yazısı kaldır
User prompt
Escort görevinde NPC hedef koordinata gitsin, biz yanında gidelim.
User prompt
Korsanın saldırı ve savunma gücünü, bulunduğu seviyesine oranla yükselt.
User prompt
Wave 1 iken 1-3 seviye, wave 2 iken 3-5 seviye... diye orantılı şekilde yükselsin.
User prompt
Her Wave yükseldiğinde korsan gemilerinin seviyeleri yükselsin. Seviyesi yükselen korsan gemilerinin canı ve saldırı gücü artsın. Ayrıca Seviyesi gemilerinin alt kısmında küçük yazı ile yazsın.
User prompt
Koordinat, Anlık olarak bulunduğumuz konumun koordinatını yazsın. Mesela NPC'den görev alıyorum ama koordinat bilmediğim için yapamıyorum.
User prompt
Ekranın sağ alt köşesine ''Reset'' butonu ekle ve bütün ilerleme tamamen sıfırlanmasını sağla. Yazı fontu Heath yazı fontu gibi olsun.
User prompt
Her korsan öldürdüğümüzde, 1-3 arasında Exp versin.
User prompt
Koordinat'ı Wave'nin sol yanına kaydır
User prompt
Seviye, Rep boyutlarını da aynı yap
User prompt
Üst kısımda bulunan yazıların tamamının font boyutunu, Koordinat yazı font boyutu ile aynı olsun.
User prompt
Kordinatı %25 oranında sola kaydır
User prompt
Kordinatı %20 oranında sola kaydır
User prompt
kordinatı %30 oranında küçült.
User prompt
Kordinatı, Level yazısının üzerine gelecek şekilde kaydır. Ayrıca %10 oranında büyüt ve güncel konumu anlık olarak göstersin.
User prompt
eklediğin kordinatı sağa kaydır ve %50 oranında küçült. Ayrıca anlık olarak göstersin.
User prompt
Wave sol yanına, küçük şekilde haritada bulunduğumuz kordinat yazsın.
User prompt
Korsan Base'leri olsun bazı yerlerde, Korsan Base etrafında birçok korsan olsun ve bu base anlık; 10 korsan saldırı ve savunma gücüne sahip olsun. (Takılma, takılınca yeniden başlat)
User prompt
Saldırı Mesafesini %10 arttır.
User prompt
Saldırı alabilen veya saldırı yapabilen herşeyin can barı olsun.
User prompt
Avcılık görevinde, Kabul edildiği zaman görevi NPC yönetsin. Belli bir süre veya korsan sayısı belirtilsin görevde.
User prompt
Yada birden fazla korsanın, NPC'ye saldıracağı ve NPC yardım isteğinde bulunması konusunda sistem ekle. Kabul edersek, korsanlardan NPC'yi koruyalım ve korsanları öldürünce NPC ödül versin. Kabul etmez isek, NPC'ye ilgili korsanlar saldırsın ve yok etsin. Böylece iyi ve kötü rep kazanalım. NPC'ler ona göre bize ödüller versinler.
User prompt
Bu tarz görevlerin, gerçekleşmesi için npc durumu yönetsin. Korsan saldırı görevleri de olsun. NPC ile saldıralım birlikte saldıralım felan.
User prompt
Escort görevini yapacağım ama npc sabit yerde duruyor.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Asteroid = Container.expand(function () { var self = Container.call(this); var asteroidGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, tint: 0x8B4513, scaleX: 2, scaleY: 2 }); self.health = 50; self.resources = Math.floor(Math.random() * 10) + 5; self.vx = (Math.random() - 0.5) * 0.5; self.vy = (Math.random() - 0.5) * 0.5; self.rotationSpeed = (Math.random() - 0.5) * 0.02; self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xffffff, 100); }; self.update = function () { self.x += self.vx; self.y += self.vy; self.rotation += self.rotationSpeed; }; return self; }); // Black Hole Hazard Class var BlackHole = Container.expand(function () { var self = Container.call(this); var bhGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 8, tint: 0x222222 }); self.radius = 200; self.pullStrength = 0.7 + Math.random() * 0.5; self.damageRadius = 120; self.update = function () { // Animate black hole bhGraphics.rotation += 0.03; // Pull ship if in range var dx = ship.x - self.x; var dy = ship.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.radius) { var pull = (self.radius - dist) / self.radius * self.pullStrength; ship.x -= dx / dist * pull; ship.y -= dy / dist * pull; // Camera follows ship, so move all objects accordingly for (var i = 0; i < stars.length; i++) { stars[i].x -= dx / dist * pull; stars[i].y -= dy / dist * pull; } for (var i = 0; i < npcs.length; i++) { npcs[i].x -= dx / dist * pull; npcs[i].y -= dy / dist * pull; } for (var i = 0; i < pirates.length; i++) { pirates[i].x -= dx / dist * pull; pirates[i].y -= dy / dist * pull; } for (var i = 0; i < coins.length; i++) { coins[i].x -= dx / dist * pull; coins[i].y -= dy / dist * pull; } for (var i = 0; i < resources.length; i++) { resources[i].x -= dx / dist * pull; resources[i].y -= dy / dist * pull; } for (var i = 0; i < bullets.length; i++) { bullets[i].x -= dx / dist * pull; bullets[i].y -= dy / dist * pull; } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].x -= dx / dist * pull; enemyBullets[i].y -= dy / dist * pull; } for (var i = 0; i < asteroids.length; i++) { asteroids[i].x -= dx / dist * pull; asteroids[i].y -= dy / dist * pull; } for (var i = 0; i < upgradeStations.length; i++) { upgradeStations[i].x -= dx / dist * pull; upgradeStations[i].y -= dy / dist * pull; } for (var i = 0; i < boostParticles.length; i++) { boostParticles[i].x -= dx / dist * pull; boostParticles[i].y -= dy / dist * pull; } for (var i = 0; i < explosions.length; i++) { explosions[i].x -= dx / dist * pull; explosions[i].y -= dy / dist * pull; } } // Damage ship if too close if (dist < self.damageRadius) { if (!self.lastDamaged || LK.ticks - self.lastDamaged > 30) { ship.takeDamage(10); self.lastDamaged = LK.ticks; LK.effects.flashObject(ship, 0x000000, 200); } } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = 10; self.directionX = 0; self.directionY = -1; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; }; return self; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.value = Math.floor(Math.random() * 10) + 5; self.update = function () { self.rotation += 0.05; }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 5; self.directionX = 0; self.directionY = 0; self.update = function () { self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; }; return self; }); // HealthBar class for displaying health above entities var HealthBar = Container.expand(function () { var self = Container.call(this); // width, height, color, maxValue, getValueFn self._width = 60; self._height = 10; self._color = 0x00ff00; self._maxValue = 100; self._getValueFn = null; self._getMaxFn = null; self._bg = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: self._width / 40, scaleY: self._height / 40, tint: 0x222222 }); self._bar = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5, scaleX: (self._width - 4) / 40, scaleY: (self._height - 4) / 40, tint: self._color }); self._bar.x = 0; self._bar.y = 0; self.set = function (opts) { self._maxValue = opts.maxValue || 100; self._getValueFn = opts.getValueFn; self._getMaxFn = opts.getMaxFn; self._color = opts.color || 0x00ff00; self._bar.tint = self._color; if (opts.width) { self._width = opts.width; self._bg.scaleX = self._width / 40; self._bar.scaleX = (self._width - 4) / 40; } if (opts.height) { self._height = opts.height; self._bg.scaleY = self._height / 40; self._bar.scaleY = (self._height - 4) / 40; } }; self.update = function () { var value = self._getValueFn ? self._getValueFn() : self._maxValue; var maxValue = self._getMaxFn ? self._getMaxFn() : self._maxValue; var ratio = Math.max(0, Math.min(1, value / maxValue)); // Color: green > yellow > red if (ratio > 0.6) { self._bar.tint = 0x00ff00; } else if (ratio > 0.3) { self._bar.tint = 0xffff00; } else { self._bar.tint = 0xff0000; } self._bar.scaleX = (self._width - 4) * ratio / 40; }; return self; }); var NPC = Container.expand(function () { var self = Container.call(this); var npcGraphics = self.attachAsset('npc', { anchorX: 0.5, anchorY: 0.5 }); var questTypes = ['trade', 'delivery', 'explore', 'escort', 'hunt', 'puzzle', 'defend']; // 10% şansla yeni 'defend' questType ata, yoksa normal random if (Math.random() < 0.10) { self.questType = 'defend'; } else { self.questType = questTypes[Math.floor(Math.random() * (questTypes.length - 1))]; } self.questActive = true; self.questProgress = 0; self.questTarget = null; self.reward = Math.floor(Math.random() * 80) + 30; self.dialogueStep = 0; self.hasTraded = false; self.isAI = true; // AI-driven self.baseY = 0; self.moveSpeed = 1 + Math.random() * 2; self.moveAngle = Math.random() * Math.PI * 2; self.wanderTimer = 0; self.lastAIAction = 0; self.targetX = null; self.targetY = null; self.rpgName = "NPC-" + Math.floor(Math.random() * 10000); self.rpgMood = Math.random() < 0.5 ? "friendly" : "neutral"; self.rpgInventory = { metal: Math.floor(Math.random() * 10), energy: Math.floor(Math.random() * 10), coins: Math.floor(Math.random() * 30) }; self.rpgTradeOffer = { give: Math.random() < 0.5 ? "metal" : "energy", giveAmount: Math.floor(Math.random() * 5) + 1, want: Math.random() < 0.5 ? "energy" : "metal", wantAmount: Math.floor(Math.random() * 5) + 1 }; // --- AI/Quest logic --- self.update = function () { // Pause logic: If pauseUntil is set and not expired, skip movement if (self.pauseUntil && LK.ticks < self.pauseUntil) { // Still paused, only float animation self.y += Math.sin(LK.ticks * 0.05) * 0.5; return; } // AI: Sometimes move toward a random point, sometimes wander self.wanderTimer++; if (self.wanderTimer > 120 + Math.random() * 120) { if (Math.random() < 0.5) { // Pick a random point to move toward (simulate AI goal seeking) self.targetX = self.x + (Math.random() - 0.5) * 800; self.targetY = self.y + (Math.random() - 0.5) * 800; } else { self.targetX = null; self.targetY = null; } self.moveAngle = Math.random() * Math.PI * 2; self.wanderTimer = 0; } // Move toward target if set, else wander if (self.targetX !== null && self.targetY !== null) { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.x += dx / dist * self.moveSpeed; self.y += dy / dist * self.moveSpeed; self.moveAngle = Math.atan2(dy, dx); } else { self.targetX = null; self.targetY = null; } } else { self.x += Math.cos(self.moveAngle) * self.moveSpeed; self.y += Math.sin(self.moveAngle) * self.moveSpeed; } // Float animation on top of movement self.y += Math.sin(LK.ticks * 0.05) * 0.5; // --- Defend quest: spawn pirates, request help, handle accept/reject, rep and reward --- if (self.questActive && self.questType === 'defend') { // 1. Eğer henüz korsan saldırısı başlatılmadıysa, başlat if (!self._defendStarted) { // 3-5 korsan spawn et, NPC'yi hedeflesin var squadCount = 3 + Math.floor(Math.random() * 3); self._defendPirates = spawnPirateSquad(self.x, self.y, squadCount, self); self._defendStarted = true; self._defendHelpRequested = false; self._defendHelpAccepted = undefined; // undefined: karar verilmedi, true: kabul, false: reddedildi self._defendHelpPanelShown = false; self._defendPiratesAlive = squadCount; self._defendRewardGiven = false; self._defendPirateDestroyed = 0; self._defendPirateDestroyedLast = 0; self._defendPirateDestroyedTicks = 0; self._defendPirateDestroyedTotal = squadCount; self._defendPirateDestroyedList = []; self._defendPirateDestroyedRepGiven = false; } // 2. Eğer oyuncu yakınsa ve yardım isteği henüz gösterilmediyse, Accept/Reject panelini göster var playerDist = Math.sqrt(Math.pow(ship.x - self.x, 2) + Math.pow(ship.y - self.y, 2)); if (!self._defendHelpPanelShown && playerDist < 180 && self._defendHelpAccepted === undefined) { // Accept/Reject paneli göster if (!self._questDecisionPanel) { // Remove any previous quest panel if (game._questDecisionPanel && game._questDecisionPanel.parent) { game._questDecisionPanel.parent.removeChild(game._questDecisionPanel); game._questDecisionPanel = null; } if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) { game._questDecisionAcceptBtn.parent.removeChild(game._questDecisionAcceptBtn); game._questDecisionAcceptBtn = null; } if (game._questDecisionRejectBtn && game._questDecisionRejectBtn.parent) { game._questDecisionRejectBtn.parent.removeChild(game._questDecisionRejectBtn); game._questDecisionRejectBtn = null; } // Panel background var panel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, x: ship.x, y: ship.y - 180, scaleX: 7, scaleY: 2, tint: 0x222244 }); // Quest text var questText = new Text2("Korsanlar saldırıyor! Yardım eder misin?", { size: 38, fill: 0xffffff, align: "center" }); questText.anchor.set(0.5, 0.5); questText.x = ship.x; questText.y = ship.y - 200; // Accept button var acceptBtn = new Text2("Yardım Et", { size: 44, fill: 0x00ff99, align: "center" }); acceptBtn.anchor.set(0.5, 0.5); acceptBtn.x = ship.x - 100; acceptBtn.y = ship.y - 120; // Reject button var rejectBtn = new Text2("Yardım Etme", { size: 44, fill: 0xff4444, align: "center" }); rejectBtn.anchor.set(0.5, 0.5); rejectBtn.x = ship.x + 100; rejectBtn.y = ship.y - 120; // Add to game game.addChild(panel); game.addChild(questText); game.addChild(acceptBtn); game.addChild(rejectBtn); // Store references for cleanup self._questDecisionPanel = panel; self._questDecisionText = questText; self._questDecisionAcceptBtn = acceptBtn; self._questDecisionRejectBtn = rejectBtn; game._questDecisionPanel = panel; game._questDecisionAcceptBtn = acceptBtn; game._questDecisionRejectBtn = rejectBtn; game._questDecisionText = questText; game._questDecisionNPC = self; acceptBtn._isQuestAcceptBtn = true; rejectBtn._isQuestRejectBtn = true; acceptBtn._questNPC = self; rejectBtn._questNPC = self; acceptBtn._questType = self.questType; rejectBtn._questType = self.questType; } self._defendHelpPanelShown = true; } // 3. Oyuncu Accept/Reject panelinden karar verirse, _defendHelpAccepted güncellenir (game.down'da) // 4. Eğer yardım kabul edildiyse, korsanlar oyuncuya ve NPC'ye saldırır, oyuncu korsanları öldürmeli if (self._defendHelpAccepted === true) { // Korsanlar hem NPC'ye hem oyuncuya saldırır, oyuncu korsanları öldürmeli // Korsanlar update fonksiyonunda zaten NPC'yi hedefliyor // Eğer tüm korsanlar öldüyse, ödül ver ve rep artır var alive = 0; for (var i = 0; i < self._defendPirates.length; i++) { if (!self._defendPirates[i]._destroyed) alive++; } if (alive === 0 && !self._defendRewardGiven) { // Görev tamamlandı, ödül ver playerCoins += self.reward + 50; playerGoodRep += 10; self.questProgress = 1; self._defendRewardGiven = true; questsCompleted++; // Görev tamamlandı mesajı göster var completeLabel = new Text2("NPC kurtarıldı! Ödül: " + (self.reward + 50) + " coin\n+10 İyi Rep", { size: 32, fill: 0x00ff99, align: "center" }); completeLabel.anchor.set(0.5, 0.5); completeLabel.x = self.x; completeLabel.y = self.y + 110; game.addChild(completeLabel); self._npcInteractionLabel = completeLabel; self._npcInteractionLabelExpire = LK.ticks + 150; self.pauseUntil = LK.ticks + 120; self.questActive = false; self._questCompleteShown = true; updateUI(); saveProgress(); } } // 5. Eğer yardım reddedildiyse, korsanlar sadece NPC'ye saldırır, NPC yok edilirse kötü rep ver if (self._defendHelpAccepted === false) { // Korsanlar sadece NPC'yi hedefler var alive = 0; for (var i = 0; i < self._defendPirates.length; i++) { if (!self._defendPirates[i]._destroyed) alive++; } // NPC öldüyse ve rep verilmediyse if (self.health !== undefined && self.health <= 0 && !self._defendPirateDestroyedRepGiven) { playerBadRep += 10; self._defendPirateDestroyedRepGiven = true; // Kötü rep mesajı var failLabel = new Text2("NPC yok edildi!\n+10 Kötü Rep", { size: 32, fill: 0xff4444, align: "center" }); failLabel.anchor.set(0.5, 0.5); failLabel.x = self.x; failLabel.y = self.y + 110; game.addChild(failLabel); self._npcInteractionLabel = failLabel; self._npcInteractionLabelExpire = LK.ticks + 150; self.pauseUntil = LK.ticks + 120; self.questActive = false; self._questCompleteShown = true; updateUI(); saveProgress(); } } } // --- RPG/Quest/Adventure logic: update quest progress if active --- if (self.questActive && self.questType === 'explore' && self.questTarget) { // If player is close to quest target, complete quest var dx = ship.x - self.questTarget.x; var dy = ship.y - self.questTarget.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.questProgress = 1; } } if (self.questActive && self.questType === 'escort' && self.questTarget) { // Oyuncu NPC'ye yakınsa, NPC hedefe doğru hareket etmeye başlasın, uzaksa beklesin var playerDist = Math.sqrt(Math.pow(ship.x - self.x, 2) + Math.pow(ship.y - self.y, 2)); if (self.questProgress === 0) { if (playerDist < 220) { // Hedefe doğru hareket et var tdx = self.questTarget.x - self.x; var tdy = self.questTarget.y - self.y; var tdist = Math.sqrt(tdx * tdx + tdy * tdy); if (tdist > 10) { self.x += tdx / tdist * self.moveSpeed; self.y += tdy / tdist * self.moveSpeed; self.moveAngle = Math.atan2(tdy, tdx); } self._escortWaiting = false; } else { // Oyuncu uzaksa bekle, "Bekliyorum..." mesajı göster if (!self._escortWaiting) { if (self._npcText && self._npcText.parent) { self._npcText.parent.removeChild(self._npcText); } self._npcText = new Text2(self.rpgName + ": Seni bekliyorum, lütfen yakınımda kal!", { size: 32, fill: 0x00ffcc, align: "center" }); self._npcText.anchor.set(0.5, 1); self._npcText.x = self.x; self._npcText.y = self.y - 70; if (game && game.addChild) game.addChild(self._npcText); self._escortWaiting = true; } } } // Eğer NPC hedefe ulaştıysa görevi tamamla var dx = self.x - self.questTarget.x; var dy = self.y - self.questTarget.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.questProgress = 1; // Hedefe ulaşınca bekleme mesajını kaldır if (self._npcText && self._npcText.parent) { self._npcText.parent.removeChild(self._npcText); self._npcText = null; } self._escortWaiting = false; } } if (self.questActive && self.questType === 'hunt') { // Avcılık görevi başlatıldıysa, görev süresi ve hedef sayısı belirle if (!self._huntStarted) { // Görev kabul edildiğinde başlatılır self._huntStarted = true; // Görev süresi (ör: 30 saniye = 1800 tick) self._huntTimeLimit = 1800 + Math.floor(Math.random() * 600); // 30-40 sn arası self._huntTimeStart = LK.ticks; // Kaç korsan öldürülmesi gerektiği self._huntTargetCount = 2 + Math.floor(Math.random() * 3); // 2-4 arası self._huntKilled = 0; self._huntTargetList = []; // Hedef korsanları seç var availablePirates = []; for (var i = 0; i < pirates.length; i++) { if (!pirates[i]._destroyed) availablePirates.push(pirates[i]); } // Eğer yeterli korsan yoksa, yeni korsan spawn et while (availablePirates.length < self._huntTargetCount) { spawnPirate(); for (var i = 0; i < pirates.length; i++) { if (!pirates[i]._destroyed && availablePirates.indexOf(pirates[i]) === -1) { availablePirates.push(pirates[i]); } } } // Hedef korsanları seç ve işaretle for (var i = 0; i < self._huntTargetCount; i++) { var p = availablePirates[i % availablePirates.length]; self._huntTargetList.push(p); } self.questTarget = self._huntTargetList[0]; self._huntCurrentTargetIndex = 0; self._huntComplete = false; self._huntFailed = false; } // Görev süresi kontrolü var elapsed = LK.ticks - self._huntTimeStart; if (!self._huntComplete && !self._huntFailed && elapsed > self._huntTimeLimit) { // Süre doldu, görev başarısız self._huntFailed = true; self.questActive = false; self.questProgress = -1; // Kısa süreli başarısızlık mesajı var failLabel = new Text2("Av görevi başarısız! Süre doldu.", { size: 32, fill: 0xff4444, align: "center" }); failLabel.anchor.set(0.5, 0.5); failLabel.x = self.x; failLabel.y = self.y + 110; game.addChild(failLabel); self._npcInteractionLabel = failLabel; self._npcInteractionLabelExpire = LK.ticks + 150; self.pauseUntil = LK.ticks + 120; } // Görev başarısızsa, başka işlem yapma if (self._huntFailed) return; // Hedef korsan öldürüldüyse, bir sonrakine geç if (self._huntTargetList && self._huntCurrentTargetIndex < self._huntTargetList.length) { var currentTarget = self._huntTargetList[self._huntCurrentTargetIndex]; if (currentTarget && currentTarget._destroyed) { self._huntKilled++; self._huntCurrentTargetIndex++; if (self._huntCurrentTargetIndex < self._huntTargetList.length) { self.questTarget = self._huntTargetList[self._huntCurrentTargetIndex]; } else { self.questTarget = null; } } } // Görev tamamlandı mı? if (!self._huntComplete && self._huntKilled >= self._huntTargetCount) { self._huntComplete = true; self.questProgress = 1; self.questActive = false; playerCoins += self.reward + 30; questsCompleted++; var completeLabel = new Text2("Av görevi tamamlandı! Ödül: " + (self.reward + 30) + " coin", { size: 32, fill: 0x00ff99, align: "center" }); completeLabel.anchor.set(0.5, 0.5); completeLabel.x = self.x; completeLabel.y = self.y + 110; game.addChild(completeLabel); self._npcInteractionLabel = completeLabel; self._npcInteractionLabelExpire = LK.ticks + 150; self.pauseUntil = LK.ticks + 120; updateUI(); saveProgress(); } // Hedef korsan varsa, ona saldır if (self.questTarget && !self.questTarget._destroyed) { var dx = self.questTarget.x - self.x; var dy = self.questTarget.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); // Saldırı mesafesi %10 arttırıldı (120 -> 132) if (dist > 132) { self.x += dx / dist * self.moveSpeed * 1.2; self.y += dy / dist * self.moveSpeed * 1.2; self.moveAngle = Math.atan2(dy, dx); } // Saldırı: NPC ateş etsin (her 40 tickte bir) if (!self._lastAttack || LK.ticks - self._lastAttack > 40) { var bullet = new Bullet(); bullet.x = self.x; bullet.y = self.y; var angle = Math.atan2(self.questTarget.y - self.y, self.questTarget.x - self.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; bullets.push(bullet); if (game && game.addChild) game.addChild(bullet); self._lastAttack = LK.ticks; } // Eğer oyuncu da yakınsa, birlikte saldırı efekti // Saldırı mesafesi %10 arttırıldı (200 -> 220) var playerDist = Math.sqrt(Math.pow(ship.x - self.questTarget.x, 2) + Math.pow(ship.y - self.questTarget.y, 2)); if (playerDist < 220 && dist < 220) { self.questTarget.moveAngle = Math.atan2(ship.y - self.questTarget.y, ship.x - self.questTarget.x); } } } if (self.questActive && self.questType === 'puzzle') { // Simulate puzzle solved after some time if (LK.ticks % 600 === 0) { self.questProgress = 1; } } }; // --- RPG/Adventure/Trade: interaction method for player tap/close --- self.interact = function () { // Dialogue/quest/trade logic if (!self.questActive) return "I'm just exploring the stars!"; // Helper for EXP gain and level up function gainEXP(amount) { playerEXP += amount; var leveledUp = false; while (playerEXP >= expToNext(playerLevel)) { playerEXP -= expToNext(playerLevel); playerLevel++; leveledUp = true; } updateUI(); if (leveledUp) { LK.effects.flashObject(ship, 0x00ffcc, 800); return "Level Up! Now Level " + playerLevel + "!"; } return null; } if (self.questType === 'trade') { if (!self.hasTraded) { // Offer trade if (self.rpgTradeOffer.give === 'metal' && playerMetal >= self.rpgTradeOffer.wantAmount) { playerMetal -= self.rpgTradeOffer.wantAmount; playerEnergy += self.rpgTradeOffer.giveAmount; self.hasTraded = true; var expMsg = gainEXP(10 + Math.floor(Math.random() * 10)); return self.rpgName + ": Thanks for the trade! +" + self.rpgTradeOffer.giveAmount + " energy!" + (expMsg ? "\n" + expMsg : ""); } else if (self.rpgTradeOffer.give === 'energy' && playerEnergy >= self.rpgTradeOffer.wantAmount) { playerEnergy -= self.rpgTradeOffer.wantAmount; playerMetal += self.rpgTradeOffer.giveAmount; self.hasTraded = true; var expMsg = gainEXP(10 + Math.floor(Math.random() * 10)); return self.rpgName + ": Thanks for the trade! +" + self.rpgTradeOffer.giveAmount + " metal!" + (expMsg ? "\n" + expMsg : ""); } else { return self.rpgName + ": I can trade " + self.rpgTradeOffer.giveAmount + " " + self.rpgTradeOffer.give + " for " + self.rpgTradeOffer.wantAmount + " " + self.rpgTradeOffer.want + "."; } } else { return self.rpgName + ": Good luck out there!"; } } if (self.questType === 'delivery') { if (self.questProgress === 0) { // Assign delivery quest: go to a random point if (!self.questTarget) { self.questTarget = { x: self.x + (Math.random() - 0.5) * 2000, y: self.y + (Math.random() - 0.5) * 2000 }; return self.rpgName + ": Can you deliver this package to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")?"; } else { var dx = ship.x - self.questTarget.x; var dy = ship.y - self.questTarget.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.questProgress = 1; playerCoins += self.reward; questsCompleted++; var expMsg = gainEXP(40 + Math.floor(Math.random() * 20)); return self.rpgName + ": Delivery complete! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : ""); } else { return self.rpgName + ": Please deliver to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")"; } } } else { return self.rpgName + ": Thank you for your help!"; } } if (self.questType === 'explore') { if (self.questProgress === 0) { if (!self.questTarget) { self.questTarget = { x: self.x + (Math.random() - 0.5) * 2000, y: self.y + (Math.random() - 0.5) * 2000 }; return self.rpgName + ": Can you explore the area at (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")?"; } else { var dx = ship.x - self.questTarget.x; var dy = ship.y - self.questTarget.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.questProgress = 1; playerCoins += self.reward; questsCompleted++; var expMsg = gainEXP(30 + Math.floor(Math.random() * 15)); return self.rpgName + ": Thanks for exploring! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : ""); } else { return self.rpgName + ": Please explore (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")"; } } } else { return self.rpgName + ": You are a true explorer!"; } } if (self.questType === 'escort') { if (self.questProgress === 0) { if (!self.questTarget) { self.questTarget = { x: self.x + (Math.random() - 0.5) * 2000, y: self.y + (Math.random() - 0.5) * 2000 }; return self.rpgName + ": Can you escort me to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")?"; } else { var dx = self.x - self.questTarget.x; var dy = self.y - self.questTarget.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 80) { self.questProgress = 1; playerCoins += self.reward; questsCompleted++; var expMsg = gainEXP(35 + Math.floor(Math.random() * 15)); return self.rpgName + ": Safe arrival! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : ""); } else { // Move toward target if player is close var pdx = ship.x - self.x; var pdy = ship.y - self.y; var pdist = Math.sqrt(pdx * pdx + pdy * pdy); if (pdist < 200) { var tdx = self.questTarget.x - self.x; var tdy = self.questTarget.y - self.y; var tdist = Math.sqrt(tdx * tdx + tdy * tdy); if (tdist > 10) { self.x += tdx / tdist * self.moveSpeed; self.y += tdy / tdist * self.moveSpeed; } } return self.rpgName + ": Please escort me to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")"; } } } else { return self.rpgName + ": Thank you for the escort!"; } } if (self.questType === 'hunt') { if (self.questProgress === 0) { if (!self.questTarget) { // Assign a random pirate as target if (pirates.length > 0) { self.questTarget = pirates[Math.floor(Math.random() * pirates.length)]; return self.rpgName + ": Can you defeat pirate #" + self.questTarget.rpgName + "?"; } else { return self.rpgName + ": No pirates nearby, come back later!"; } } else { if (self.questTarget._destroyed) { self.questProgress = 1; playerCoins += self.reward; questsCompleted++; var expMsg = gainEXP(50 + Math.floor(Math.random() * 20)); return self.rpgName + ": Pirate defeated! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : ""); } else { return self.rpgName + ": Please defeat pirate #" + (self.questTarget.rpgName || "unknown"); } } } else { return self.rpgName + ": You are a true hero!"; } } if (self.questType === 'puzzle') { if (self.questProgress === 0) { return self.rpgName + ": Solve my puzzle! (Wait a bit...)"; } else { playerCoins += self.reward; questsCompleted++; self.questProgress = 2; var expMsg = gainEXP(25 + Math.floor(Math.random() * 10)); return self.rpgName + ": Puzzle solved! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : ""); } } return self.rpgName + ": Safe travels!"; }; return self; }); var Pirate = Container.expand(function () { var self = Container.call(this); var pirateGraphics = self.attachAsset('pirate', { anchorX: 0.5, anchorY: 0.5 }); // --- Pirate Level & Scaling --- self.level = typeof waveNumber !== "undefined" ? 1 + waveNumber : 1; self.health = 30 + (self.level - 1) * 10; self.speed = 2 + Math.floor((self.level - 1) / 10) * 0.2; // Slight speed up every 10 waves self.fireRate = 60 - Math.min((self.level - 1) * 2, 30); // Faster fire at higher levels self.lastFire = 0; self.loot = Math.floor(Math.random() * 30) + 10 + (self.level - 1) * 2; self.moveAngle = Math.random() * Math.PI * 2; self.patrolTimer = 0; self.aggroRange = 600; // Korsan saldırı ve savunma gücü seviyeye göre orantılı artar self.damage = 5 + Math.floor((self.level - 1) * 1.5); // Saldırı gücü daha hızlı artar self.defense = 2 + Math.floor((self.level - 1) * 1.2); // Savunma gücü de seviyeye göre artar // --- Level Text --- self._levelText = new Text2("Lv." + self.level, { size: 22, fill: 0xcccccc, align: "center" }); self._levelText.anchor.set(0.5, 0); self._levelText.x = 0; self._levelText.y = 40; // Under the pirate sprite self.addChild(self._levelText); // Level text only, defense text removed self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xffffff, 100); }; self.update = function () { // Update level text position in case of movement if (self._levelText) { self._levelText.x = 0; self._levelText.y = pirateGraphics.height / 2 + 4; self._levelText.setText("Lv." + self.level); } // Defense text removed // Movement AI self.patrolTimer++; if (self.patrolTimer > 180) { self.moveAngle = Math.random() * Math.PI * 2; self.patrolTimer = 0; } // Patrol movement if (self._squadTargetNPC && self._squadTargetNPC.questType === 'defend' && self._squadTargetNPC.questActive) { // Korsan, NPC'yi hedefle var target = self._squadTargetNPC; // Eğer defend quest'te yardım kabul edildiyse, oyuncuya da saldırabilir if (target._defendHelpAccepted === true && Math.random() < 0.5) { // %50 ihtimalle oyuncuya saldır target = Math.random() < 0.5 ? self._squadTargetNPC : ship; } var dx = target.x - self.x; var dy = target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 10) { self.x += dx / dist * self.speed; self.y += dy / dist * self.speed; self.moveAngle = Math.atan2(dy, dx); } // Ateş et if (LK.ticks - self.lastFire > self.fireRate) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var angle = Math.atan2(target.y - self.y, target.x - self.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; enemyBullets.push(bullet); if (game && game.addChild) game.addChild(bullet); self.lastFire = LK.ticks; } } else { self.x += Math.cos(self.moveAngle) * self.speed * 0.5; self.y += Math.sin(self.moveAngle) * self.speed * 0.5; } }; return self; }); // Pirate Base Class var PirateBase = Container.expand(function () { var self = Container.call(this); var baseGraphics = self.attachAsset('pirate', { anchorX: 0.5, anchorY: 0.5, tint: 0x990000, scaleX: 3, scaleY: 3 }); self.health = 300; self.maxHealth = 300; self.attackPower = 10; self.defensePower = 10; self.spawnRadius = 350; self.pirates = []; self.lastPirateSpawn = 0; self.maxPirates = 10; self._destroyed = false; // Health bar self._healthBar = new HealthBar(); self._healthBar.set({ maxValue: function maxValue() { return self.maxHealth; }, getValueFn: function getValueFn() { return self.health; }, getMaxFn: function getMaxFn() { return self.maxHealth; }, width: 120, height: 16, color: 0xff0000 }); self._healthBar.y = -120; self.addChild(self._healthBar); self.takeDamage = function (amount) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 120); if (self.health <= 0 && !self._destroyed) { self.health = 0; self._destroyed = true; // Remove all pirates around base for (var i = 0; i < self.pirates.length; i++) { if (self.pirates[i] && !self.pirates[i]._destroyed) { self.pirates[i].destroy(); } } // Explosion effect createExplosion(self.x, self.y); // Floating label var label = new Text2("Korsan Üssü Yok Edildi!", { size: 48, fill: 0xffcc00, align: "center" }); label.anchor.set(0.5, 0.5); label.x = self.x; label.y = self.y - 180; if (game && game.addChild) game.addChild(label); self._destroyed = true; self.destroy(); } }; self.update = function () { // Health bar update if (self._healthBar && self._healthBar.update) self._healthBar.update(); // Remove dead pirates from list for (var i = self.pirates.length - 1; i >= 0; i--) { if (!self.pirates[i] || self.pirates[i]._destroyed) { self.pirates.splice(i, 1); } } // Spawn pirates if less than max if (!self._destroyed && self.pirates.length < self.maxPirates && LK.ticks - self.lastPirateSpawn > 90) { var pirate = new Pirate(); var angle = Math.random() * Math.PI * 2; pirate.x = self.x + Math.cos(angle) * (self.spawnRadius + Math.random() * 60); pirate.y = self.y + Math.sin(angle) * (self.spawnRadius + Math.random() * 60); pirate.health = 30 + self.attackPower * 2; pirate.damage = 5 + self.attackPower; pirate.rpgName = "BaseKorsan-" + Math.floor(Math.random() * 10000); pirate._baseRef = self; // Add health bar to pirate pirate._healthBar = new HealthBar(); pirate._healthBar.set({ maxValue: function maxValue() { return pirate.health > 0 ? pirate.health : 0; }, getValueFn: function getValueFn() { return pirate.health > 0 ? pirate.health : 0; }, getMaxFn: function getMaxFn() { return 30 + self.attackPower * 2; }, width: 60, height: 10 }); pirate._healthBar.y = -60; pirate.addChild(pirate._healthBar); pirates.push(pirate); self.pirates.push(pirate); if (game && game.addChild) game.addChild(pirate); self.lastPirateSpawn = LK.ticks; } // Base defense: shoot at player if close var distToShip = Math.sqrt(Math.pow(ship.x - self.x, 2) + Math.pow(ship.y - self.y, 2)); if (!self._destroyed && distToShip < self.spawnRadius + 80 && LK.ticks % 30 === 0) { var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y; var angle = Math.atan2(ship.y - self.y, ship.x - self.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; bullet.damage = 10 + self.attackPower; enemyBullets.push(bullet); if (game && game.addChild) game.addChild(bullet); } }; return self; }); var Resource = Container.expand(function () { var self = Container.call(this); var resourceGraphics = self.attachAsset('resource', { anchorX: 0.5, anchorY: 0.5 }); self.type = Math.random() < 0.5 ? 'metal' : 'energy'; self.amount = Math.floor(Math.random() * 5) + 1; self.update = function () { self.rotation += 0.03; }; return self; }); var Ship = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('ship', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; self.shield = 50; self.maxShield = 50; self.shieldRegenDelay = 0; self.speed = 5; self.fireRate = 10; self.damage = 10; self.lastFire = 0; self.boostSpeed = 0; self.boostCooldown = 0; self.takeDamage = function (amount) { // Shield absorbs damage first if (self.shield > 0) { var shieldDamage = Math.min(amount, self.shield); self.shield -= shieldDamage; amount -= shieldDamage; LK.effects.flashObject(self, 0x0088ff, 100); self.shieldRegenDelay = 180; // 3 seconds delay before shield regen } if (amount > 0) { self.health -= amount; LK.effects.flashObject(self, 0xff0000, 200); } if (self.health <= 0) { self.health = 0; LK.showGameOver(); } }; self.update = function () { // Shield regeneration if (self.shieldRegenDelay > 0) { self.shieldRegenDelay--; } else if (self.shield < self.maxShield) { self.shield = Math.min(self.shield + 0.1, self.maxShield); } // Boost cooldown if (self.boostCooldown > 0) { self.boostCooldown--; } if (self.boostSpeed > 0) { self.boostSpeed -= 0.2; } }; return self; }); var Star = Container.expand(function () { var self = Container.call(this); var starGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5 }); self.speed = Math.random() * 2 + 0.5; starGraphics.alpha = Math.random() * 0.8 + 0.2; self.vx = (Math.random() - 0.5) * 0.5; self.vy = (Math.random() - 0.5) * 0.5; self.update = function () { // Slow floating movement self.x += self.vx; self.y += self.vy; }; return self; }); // Trade Station Class var TradeStation = Container.expand(function () { var self = Container.call(this); var tradeGraphics = self.attachAsset('npc', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ff99, scaleX: 2, scaleY: 2 }); self.type = 'trade'; self.rotationSpeed = 0.01; self.offerType = Math.random() < 0.5 ? 'buy' : 'sell'; // buy: station buys from player, sell: station sells to player self.resourceType = Math.random() < 0.5 ? 'metal' : 'energy'; self.amount = Math.floor(Math.random() * 10) + 5; self.price = Math.floor(Math.random() * 30) + 10; self.specialOffer = Math.random() < 0.2; // 20% chance for special upgrade offer self.specialUpgrade = null; if (self.specialOffer) { var upgrades = [{ name: 'maxHealth', label: 'Max Health +30', cost: 200 }, { name: 'maxShield', label: 'Max Shield +20', cost: 180 }, { name: 'damage', label: 'Damage +5', cost: 150 }, { name: 'speed', label: 'Speed +1', cost: 120 }]; self.specialUpgrade = upgrades[Math.floor(Math.random() * upgrades.length)]; } self.update = function () { self.rotation += self.rotationSpeed; // Pulse effect var scale = 2 + Math.sin(LK.ticks * 0.05) * 0.1; tradeGraphics.scaleX = scale; tradeGraphics.scaleY = scale; }; return self; }); var UpgradeStation = Container.expand(function () { var self = Container.call(this); var stationGraphics = self.attachAsset('pirate', { anchorX: 0.5, anchorY: 0.5, tint: 0x00ffff, scaleX: 1.5, scaleY: 1.5 }); self.type = 'upgrade'; self.upgrades = [{ name: 'health', cost: 100, metalCost: 10 }, { name: 'shield', cost: 150, metalCost: 15 }, { name: 'damage', cost: 200, energyCost: 20 }, { name: 'speed', cost: 120, energyCost: 10 }]; self.currentUpgrade = 0; self.rotationSpeed = 0.01; self.update = function () { self.rotation += self.rotationSpeed; // Pulse effect var scale = 1.5 + Math.sin(LK.ticks * 0.05) * 0.1; stationGraphics.scaleX = scale; stationGraphics.scaleY = scale; }; return self; }); // Wormhole Teleporter Class var Wormhole = Container.expand(function () { var self = Container.call(this); var whGraphics = self.attachAsset('star', { anchorX: 0.5, anchorY: 0.5, scaleX: 5, scaleY: 5, tint: 0x00ffff }); self.radius = 120; self.cooldown = 0; self.update = function () { whGraphics.rotation += 0.07; // Teleport ship if close and not on cooldown var dx = ship.x - self.x; var dy = ship.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.radius && self.cooldown <= 0) { // Teleport ship to a random far location var tx = ship.x + (Math.random() - 0.5) * 4000; var ty = ship.y + (Math.random() - 0.5) * 4000; var dx2 = tx - ship.x; var dy2 = ty - ship.y; ship.x = tx; ship.y = ty; // Move all objects to keep camera effect for (var i = 0; i < stars.length; i++) { stars[i].x -= dx2; stars[i].y -= dy2; } for (var i = 0; i < npcs.length; i++) { npcs[i].x -= dx2; npcs[i].y -= dy2; } for (var i = 0; i < pirates.length; i++) { pirates[i].x -= dx2; pirates[i].y -= dy2; } for (var i = 0; i < coins.length; i++) { coins[i].x -= dx2; coins[i].y -= dy2; } for (var i = 0; i < resources.length; i++) { resources[i].x -= dx2; resources[i].y -= dy2; } for (var i = 0; i < bullets.length; i++) { bullets[i].x -= dx2; bullets[i].y -= dy2; } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].x -= dx2; enemyBullets[i].y -= dy2; } for (var i = 0; i < asteroids.length; i++) { asteroids[i].x -= dx2; asteroids[i].y -= dy2; } for (var i = 0; i < upgradeStations.length; i++) { upgradeStations[i].x -= dx2; upgradeStations[i].y -= dy2; } for (var i = 0; i < boostParticles.length; i++) { boostParticles[i].x -= dx2; boostParticles[i].y -= dy2; } for (var i = 0; i < explosions.length; i++) { explosions[i].x -= dx2; explosions[i].y -= dy2; } for (var i = 0; i < blackHoles.length; i++) { blackHoles[i].x -= dx2; blackHoles[i].y -= dy2; } for (var i = 0; i < wormholes.length; i++) { if (wormholes[i] !== self) { wormholes[i].x -= dx2; wormholes[i].y -= dy2; } } self.cooldown = 180; LK.effects.flashScreen(0x00ffff, 500); } if (self.cooldown > 0) self.cooldown--; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ // Game variables var ship; var joystickBase; var joystickHandle; var isDragging = false; var bullets = []; var enemyBullets = []; var npcs = []; var pirates = []; var coins = []; var resources = []; var stars = []; var asteroids = []; var upgradeStations = []; var boostParticles = []; var explosions = []; var blackHoles = []; var wormholes = []; var tradeStations = []; var pirateBases = []; // NEW: array for pirate bases var tradeText = new Text2('', { size: 40, fill: 0x00ff99 }); // Helper: spawn a pirate base at a random edge, with pirates around it function spawnPirateBase() { var base = new PirateBase(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top base.x = ship.x + (Math.random() - 0.5) * 2000; base.y = ship.y - 1600; break; case 1: // Right base.x = ship.x + 1600; base.y = ship.y + (Math.random() - 0.5) * 2000; break; case 2: // Bottom base.x = ship.x + (Math.random() - 0.5) * 2000; base.y = ship.y + 1600; break; case 3: // Left base.x = ship.x - 1600; base.y = ship.y + (Math.random() - 0.5) * 2000; break; } pirateBases.push(base); game.addChild(base); // Spawn initial pirates around base for (var i = 0; i < 10; i++) { var pirate = new Pirate(); var angle = Math.PI * 2 * (i / 10); pirate.x = base.x + Math.cos(angle) * (base.spawnRadius + Math.random() * 60); pirate.y = base.y + Math.sin(angle) * (base.spawnRadius + Math.random() * 60); // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; pirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); pirate.health = 30 + (pirate.level - 1) * 10 + base.attackPower * 2; pirate.damage = 5 + Math.floor((pirate.level - 1) * 1.5) + base.attackPower; pirate.defense = 2 + Math.floor((pirate.level - 1) * 1.2) + base.defensePower; pirate.rpgName = "BaseKorsan-" + Math.floor(Math.random() * 10000); pirate._baseRef = base; // Add health bar to pirate pirate._healthBar = new HealthBar(); pirate._healthBar.set({ maxValue: function maxValue() { return pirate.health > 0 ? pirate.health : 0; }, getValueFn: function getValueFn() { return pirate.health > 0 ? pirate.health : 0; }, getMaxFn: function getMaxFn() { return 30 + base.attackPower * 2; }, width: 60, height: 10 }); pirate._healthBar.y = -60; pirate.addChild(pirate._healthBar); pirates.push(pirate); base.pirates.push(pirate); game.addChild(pirate); } } tradeText.anchor.set(0.5, 0); tradeText.y = 180; LK.gui.top.addChild(tradeText); var camera = { x: 0, y: 0 }; // --- Reputation system --- var playerGoodRep = storage.playerGoodRep || 0; var playerBadRep = storage.playerBadRep || 0; // --- Helper for multi-pirate attack quest --- function spawnPirateSquad(centerX, centerY, count, targetNPC) { var squad = []; for (var i = 0; i < count; i++) { var pirate = new Pirate(); var angle = Math.PI * 2 * (i / count); pirate.x = centerX + Math.cos(angle) * 200 + (Math.random() - 0.5) * 60; pirate.y = centerY + Math.sin(angle) * 200 + (Math.random() - 0.5) * 60; // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; pirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); pirate.health = 30 + (pirate.level - 1) * 10; pirate.damage = 5 + Math.floor((pirate.level - 1) * 1.5); pirate.defense = 2 + Math.floor((pirate.level - 1) * 1.2); pirate.rpgName = "Korsan-" + Math.floor(Math.random() * 10000); pirate._squadTargetNPC = targetNPC; pirates.push(pirate); game.addChild(pirate); squad.push(pirate); } return squad; } // Trade station tap detection (RPG/ticaret) for (var i = 0; i < tradeStations.length; i++) { var ts = tradeStations[i]; var dist = Math.sqrt(Math.pow(ts.x - ship.x, 2) + Math.pow(ts.y - ship.y, 2)); if (dist < 180) { game._lastTradeStationTap = LK.ticks; break; } } var waveNumber = 0; var enemiesKilled = 0; var totalDistance = 0; // Player stats var playerCoins = storage.coins || 0; var playerMetal = storage.metal || 0; var playerEnergy = storage.energy || 0; var questsCompleted = storage.questsCompleted || 0; // UI Elements // Calculate the unified font size (30% smaller than expText) var unifiedFontSize = Math.round(38 * 0.7); var coinText = new Text2('Coins: ' + playerCoins, { size: unifiedFontSize, fill: 0xFFFF00 }); coinText.anchor.set(0, 0); coinText.x = 120; coinText.y = 20; LK.gui.topLeft.addChild(coinText); var resourceText = new Text2('Metal: ' + playerMetal + ' Energy: ' + playerEnergy, { size: unifiedFontSize, fill: 0xFFFFFF }); resourceText.anchor.set(0, 0); resourceText.x = 120; resourceText.y = 80; LK.gui.topLeft.addChild(resourceText); var healthText = new Text2('Health: 100/100', { size: unifiedFontSize, fill: 0x00FF00 }); healthText.anchor.set(0.5, 0); LK.gui.top.addChild(healthText); var shieldText = new Text2('Shield: 50/50', { size: unifiedFontSize, fill: 0x0088FF }); shieldText.anchor.set(0.5, 0); shieldText.y = 60; LK.gui.top.addChild(shieldText); var boostText = new Text2('BOOST READY', { size: unifiedFontSize, fill: 0x00FFFF }); boostText.anchor.set(0.5, 0); boostText.y = 110; LK.gui.top.addChild(boostText); var waveText = new Text2('Wave: 1', { size: unifiedFontSize, fill: 0xFFFFFF }); waveText.anchor.set(1, 0); waveText.x = -20; waveText.y = 20; LK.gui.topRight.addChild(waveText); // --- RESET BUTTON (bottom right) --- var resetBtn = new Text2('Reset', { size: 44, fill: 0xff4444, font: "'Heath', Impact, 'Arial Black', Tahoma", // Heath-like font align: "center" }); resetBtn.anchor.set(1, 1); // bottom right resetBtn.x = -40; resetBtn.y = -40; LK.gui.bottomRight.addChild(resetBtn); // Touch/click handler for reset button resetBtn._isResetBtn = true; game._resetBtn = resetBtn; // Level/EXP system var playerLevel = storage.playerLevel || 1; var playerEXP = storage.playerEXP || 0; var expToNext = function expToNext(lv) { return 100 + (lv - 1) * 50; }; var expText = new Text2('Level: ' + playerLevel + ' EXP: ' + playerEXP + '/' + expToNext(playerLevel), { size: unifiedFontSize, fill: 0x00ffcc }); expText.anchor.set(1, 0); expText.x = -20; expText.y = 80; LK.gui.topRight.addChild(expText); // Move coordinateText to the left of waveText, decrease its size by 30%, and update its position and size in real time var coordinateText = new Text2('X: 0 Y: 0', { size: unifiedFontSize, // 30% smaller than Level text fill: 0xcccccc }); coordinateText.anchor.set(1, 0.5); // right center of the text // Position coordinateText to the left of waveText coordinateText.x = waveText.x - waveText.width - 30; coordinateText.y = waveText.y + waveText.height / 2; LK.gui.topRight.addChild(coordinateText); // Create joystick joystickBase = game.addChild(LK.getAsset('joystickBase', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 2432 })); joystickBase.alpha = 0.5; joystickHandle = game.addChild(LK.getAsset('joystickHandle', { anchorX: 0.5, anchorY: 0.5, x: 300, y: 2432 })); joystickHandle.alpha = 0.7; // Create ship ship = game.addChild(new Ship()); ship.x = 1024; ship.y = 1366; // Add health bar to ship ship._healthBar = new HealthBar(); ship._healthBar.set({ maxValue: function maxValue() { return ship.maxHealth; }, getValueFn: function getValueFn() { return ship.health; }, getMaxFn: function getMaxFn() { return ship.maxHealth; }, width: 80, height: 12 }); ship._healthBar.y = -70; ship.addChild(ship._healthBar); // Start background music LK.playMusic('bgmusic'); // Initialize star field for (var i = 0; i < 50; i++) { spawnStar(); } // Helper functions function spawnStar() { var star = new Star(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top star.x = ship.x + (Math.random() - 0.5) * 2500; star.y = ship.y - 1500; break; case 1: // Right star.x = ship.x + 1500; star.y = ship.y + (Math.random() - 0.5) * 2500; break; case 2: // Bottom star.x = ship.x + (Math.random() - 0.5) * 2500; star.y = ship.y + 1500; break; case 3: // Left star.x = ship.x - 1500; star.y = ship.y + (Math.random() - 0.5) * 2500; break; } stars.push(star); game.addChild(star); } function spawnNPC() { var npc = new NPC(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top npc.x = ship.x + (Math.random() - 0.5) * 2000; npc.y = ship.y - 1500; break; case 1: // Right npc.x = ship.x + 1500; npc.y = ship.y + (Math.random() - 0.5) * 2000; break; case 2: // Bottom npc.x = ship.x + (Math.random() - 0.5) * 2000; npc.y = ship.y + 1500; break; case 3: // Left npc.x = ship.x - 1500; npc.y = ship.y + (Math.random() - 0.5) * 2000; break; } npc.baseY = npc.y; // Add health bar to NPC (for defend/hunt/escort/delivery/explore) npc._healthBar = new HealthBar(); npc._healthBar.set({ maxValue: function maxValue() { return npc.health !== undefined ? npc.health : 100; }, getValueFn: function getValueFn() { return npc.health !== undefined ? npc.health : 100; }, getMaxFn: function getMaxFn() { return 100; }, width: 60, height: 10 }); npc._healthBar.y = -60; npc.addChild(npc._healthBar); npcs.push(npc); game.addChild(npc); } function spawnPirate() { var pirate = new Pirate(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top pirate.x = ship.x + (Math.random() - 0.5) * 1800; pirate.y = ship.y - 1400; break; case 1: // Right pirate.x = ship.x + 1400; pirate.y = ship.y + (Math.random() - 0.5) * 1800; break; case 2: // Bottom pirate.x = ship.x + (Math.random() - 0.5) * 1800; pirate.y = ship.y + 1400; break; case 3: // Left pirate.x = ship.x - 1400; pirate.y = ship.y + (Math.random() - 0.5) * 1800; break; } // Set pirate level and scale stats based on wave // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; pirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); pirate.health = 30 + (pirate.level - 1) * 10; pirate.damage = 5 + Math.floor((pirate.level - 1) * 1.5); pirate.defense = 2 + Math.floor((pirate.level - 1) * 1.2); // Add health bar to pirate pirate._healthBar = new HealthBar(); pirate._healthBar.set({ maxValue: function maxValue() { return pirate.health > 0 ? pirate.health : 0; }, getValueFn: function getValueFn() { return pirate.health > 0 ? pirate.health : 0; }, getMaxFn: function getMaxFn() { return 30 + waveNumber * 10; }, width: 60, height: 10 }); pirate._healthBar.y = -60; pirate.addChild(pirate._healthBar); pirates.push(pirate); game.addChild(pirate); } function spawnAsteroid() { var asteroid = new Asteroid(); var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: asteroid.x = ship.x + (Math.random() - 0.5) * 2200; asteroid.y = ship.y - 1600; break; case 1: asteroid.x = ship.x + 1600; asteroid.y = ship.y + (Math.random() - 0.5) * 2200; break; case 2: asteroid.x = ship.x + (Math.random() - 0.5) * 2200; asteroid.y = ship.y + 1600; break; case 3: asteroid.x = ship.x - 1600; asteroid.y = ship.y + (Math.random() - 0.5) * 2200; break; } // Add health bar to asteroid asteroid._healthBar = new HealthBar(); asteroid._healthBar.set({ maxValue: function maxValue() { return asteroid.health; }, getValueFn: function getValueFn() { return asteroid.health; }, getMaxFn: function getMaxFn() { return 50; }, width: 50, height: 8 }); asteroid._healthBar.y = -50; asteroid.addChild(asteroid._healthBar); asteroids.push(asteroid); game.addChild(asteroid); } function spawnUpgradeStation() { var station = new UpgradeStation(); station.x = ship.x + (Math.random() - 0.5) * 3000; station.y = ship.y + (Math.random() - 0.5) * 3000; upgradeStations.push(station); game.addChild(station); } function spawnTradeStation() { var ts = new TradeStation(); // Spawn from edges of visible area var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: ts.x = ship.x + (Math.random() - 0.5) * 2000; ts.y = ship.y - 1500; break; case 1: ts.x = ship.x + 1500; ts.y = ship.y + (Math.random() - 0.5) * 2000; break; case 2: ts.x = ship.x + (Math.random() - 0.5) * 2000; ts.y = ship.y + 1500; break; case 3: ts.x = ship.x - 1500; ts.y = ship.y + (Math.random() - 0.5) * 2000; break; } tradeStations.push(ts); game.addChild(ts); } function createExplosion(x, y) { for (var i = 0; i < 8; i++) { var particle = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, x: x, y: y }); particle.vx = (Math.random() - 0.5) * 10; particle.vy = (Math.random() - 0.5) * 10; particle.life = 30; explosions.push(particle); game.addChild(particle); } } function spawnBlackHole() { var bh = new BlackHole(); // Spawn far from ship, random edge var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: bh.x = ship.x + (Math.random() - 0.5) * 2000; bh.y = ship.y - 1700; break; case 1: bh.x = ship.x + 1700; bh.y = ship.y + (Math.random() - 0.5) * 2000; break; case 2: bh.x = ship.x + (Math.random() - 0.5) * 2000; bh.y = ship.y + 1700; break; case 3: bh.x = ship.x - 1700; bh.y = ship.y + (Math.random() - 0.5) * 2000; break; } blackHoles.push(bh); game.addChild(bh); } function spawnWormhole() { var wh = new Wormhole(); // Spawn far from ship, random edge var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: wh.x = ship.x + (Math.random() - 0.5) * 2000; wh.y = ship.y - 1700; break; case 1: wh.x = ship.x + 1700; wh.y = ship.y + (Math.random() - 0.5) * 2000; break; case 2: wh.x = ship.x + (Math.random() - 0.5) * 2000; wh.y = ship.y + 1700; break; case 3: wh.x = ship.x - 1700; wh.y = ship.y + (Math.random() - 0.5) * 2000; break; } wormholes.push(wh); game.addChild(wh); } function createBoostParticle() { var particle = LK.getAsset('boostParticle', { anchorX: 0.5, anchorY: 0.5, x: ship.x - Math.cos(ship.rotation - Math.PI / 2) * 50, y: ship.y - Math.sin(ship.rotation - Math.PI / 2) * 50 }); particle.vx = -Math.cos(ship.rotation - Math.PI / 2) * 5 + (Math.random() - 0.5) * 2; particle.vy = -Math.sin(ship.rotation - Math.PI / 2) * 5 + (Math.random() - 0.5) * 2; particle.life = 20; boostParticles.push(particle); game.addChild(particle); } function updateUI() { coinText.setText('Coins: ' + playerCoins); resourceText.setText('Metal: ' + playerMetal + ' Energy: ' + playerEnergy); healthText.setText('Health: ' + ship.health + '/' + ship.maxHealth); shieldText.setText('Shield: ' + Math.floor(ship.shield) + '/' + ship.maxShield); waveText.setText('Wave: ' + (waveNumber + 1)); expText.setText('Level: ' + playerLevel + ' EXP: ' + playerEXP + '/' + expToNext(playerLevel)); // Show rep in GUI if (!window.repText) { window.repText = new Text2('Rep: +' + playerGoodRep + ' / -' + playerBadRep, { size: unifiedFontSize, fill: 0xffffff }); window.repText.anchor.set(1, 0); window.repText.x = -20; window.repText.y = 140; LK.gui.topRight.addChild(window.repText); } window.repText.setText('Rep: +' + playerGoodRep + ' / -' + playerBadRep); // Update health text color if (ship.health > 60) { healthText.fill = 0x00ff00; } else if (ship.health > 30) { healthText.fill = 0xffff00; } else { healthText.fill = 0xff0000; } // Update shield text color if (ship.shield > 30) { shieldText.fill = 0x0088ff; } else if (ship.shield > 10) { shieldText.fill = 0xffff00; } else { shieldText.fill = 0xff0000; } // Update boost text if (ship.boostCooldown <= 0) { boostText.setText('BOOST READY'); boostText.fill = 0x00ffff; } else { boostText.setText('BOOST: ' + Math.ceil(ship.boostCooldown / 60) + 's'); boostText.fill = 0x888888; } storage.playerLevel = playerLevel; storage.playerEXP = playerEXP; } function saveProgress() { storage.coins = playerCoins; storage.metal = playerMetal; storage.energy = playerEnergy; storage.questsCompleted = questsCompleted; storage.playerGoodRep = playerGoodRep; storage.playerBadRep = playerBadRep; } // Event handlers game.down = function (x, y, obj) { // --- RESET BUTTON HANDLER --- if (game._resetBtn && game._resetBtn.parent) { // Convert GUI coordinates for bottomRight // LK.gui.bottomRight is anchored at (1,1) so x,y are negative from bottom right var btn = game._resetBtn; var bx = btn.x, by = btn.y; // Button is about 180x80 px, but let's use a safe area // Since anchor is (1,1), bottom right, and x/y are negative from bottom right // So, for a tap, check if x is within 200px of right edge and y within 100px of bottom // LK.gui.bottomRight: x=0,y=0 is bottom right, so x,y negative if (x > 2048 - 200 && y > 2732 - 100) { // Clear all persistent storage storage.coins = 0; storage.metal = 0; storage.energy = 0; storage.questsCompleted = 0; storage.playerLevel = 1; storage.playerEXP = 0; storage.playerGoodRep = 0; storage.playerBadRep = 0; // Optionally clear any other custom progress keys // Show a quick feedback btn.setText("Reset!"); btn.fill = 0x00ff99; // Reload game (reset all progress) LK.showGameOver(); return; } } if (Math.sqrt(Math.pow(x - joystickBase.x, 2) + Math.pow(y - joystickBase.y, 2)) < 100) { isDragging = true; joystickHandle.x = x; joystickHandle.y = y; } else if (y < 300 && ship.boostCooldown <= 0) { // Boost when tapping upper area of screen ship.boostSpeed = 10; ship.boostCooldown = 300; // 5 seconds cooldown if (LK.getSound('boost')) { LK.getSound('boost').play(); } } else { // --- Handle Accept/Reject quest button taps --- if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) { var btn = game._questDecisionAcceptBtn; var bx = btn.x, by = btn.y; // Button is about 180x80 px if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) { // Accept quest var npc = btn._questNPC; if (npc) { // Defend quest özel: yardım kabul edildi if (npc.questType === 'defend') { npc._defendHelpAccepted = true; // Show floating label for accepted var acceptLabel = new Text2("Yardım kabul edildi!", { size: 36, fill: 0x00ff99, align: "center" }); acceptLabel.anchor.set(0.5, 0.5); acceptLabel.x = npc.x; acceptLabel.y = npc.y + 110; game.addChild(acceptLabel); npc._npcInteractionLabel = acceptLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Teşekkürler! Beni korsanlardan koru!", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } else { // Mark quest as accepted (progress 1 means started) npc.questProgress = 1; // Show NPC response var acceptLabel = new Text2("Görev kabul edildi!", { size: 36, fill: 0x00ff99, align: "center" }); acceptLabel.anchor.set(0.5, 0.5); acceptLabel.x = npc.x; acceptLabel.y = npc.y + 110; game.addChild(acceptLabel); npc._npcInteractionLabel = acceptLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Harika! Görev başladı.", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } // Remove quest panel if (npc._questDecisionPanel && npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel); if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText); if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn); if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn); npc._questDecisionPanel = null; npc._questDecisionText = null; npc._questDecisionAcceptBtn = null; npc._questDecisionRejectBtn = null; game._questDecisionPanel = null; game._questDecisionAcceptBtn = null; game._questDecisionRejectBtn = null; game._questDecisionText = null; game._questDecisionNPC = null; } return; } } if (game._questDecisionRejectBtn && game._questDecisionRejectBtn.parent) { var btn = game._questDecisionRejectBtn; var bx = btn.x, by = btn.y; if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) { // Reject quest var npc = btn._questNPC; if (npc) { if (npc.questType === 'defend') { npc._defendHelpAccepted = false; // Show floating label for rejected var rejectLabel = new Text2("Yardım edilmedi.", { size: 36, fill: 0xff4444, align: "center" }); rejectLabel.anchor.set(0.5, 0.5); rejectLabel.x = npc.x; rejectLabel.y = npc.y + 110; game.addChild(rejectLabel); npc._npcInteractionLabel = rejectLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Anlaşıldı, kendi başıma savaşacağım!", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } else { // Mark quest as inactive npc.questActive = false; // Show floating label for rejected var rejectLabel = new Text2("Görev reddedildi.", { size: 36, fill: 0xff4444, align: "center" }); rejectLabel.anchor.set(0.5, 0.5); rejectLabel.x = npc.x; rejectLabel.y = npc.y + 110; game.addChild(rejectLabel); npc._npcInteractionLabel = rejectLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc.pauseUntil = LK.ticks + 120; npc._npcText && npc._npcText.parent && npc._npcText.parent.removeChild(npc._npcText); npc._npcText = new Text2(npc.rpgName + ": Belki başka zaman!", { size: 32, fill: 0x00ffcc, align: "center" }); npc._npcText.anchor.set(0.5, 1); npc._npcText.x = npc.x; npc._npcText.y = npc.y - 70; game.addChild(npc._npcText); } // Remove quest panel if (npc._questDecisionPanel && npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel); if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText); if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn); if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn); npc._questDecisionPanel = null; npc._questDecisionText = null; npc._questDecisionAcceptBtn = null; npc._questDecisionRejectBtn = null; game._questDecisionPanel = null; game._questDecisionAcceptBtn = null; game._questDecisionRejectBtn = null; game._questDecisionText = null; game._questDecisionNPC = null; } return; } } // Check for NPC tap (RPG/adventure/trade) for (var i = 0; i < npcs.length; i++) { var npc = npcs[i]; var dist = Math.sqrt(Math.pow(npc.x - ship.x, 2) + Math.pow(npc.y - ship.y, 2)); if (dist < 180) { game._lastNPCTap = LK.ticks; break; } } // --- Distress event tap detection --- if (window.distressEvent && window.distressEvent.helpBtn && window.distressEvent.ignoreBtn) { game._lastDistressTapTick = LK.ticks; game._lastDistressTapX = x; game._lastDistressTapY = y; } } }; game.move = function (x, y, obj) { if (isDragging) { var dx = x - joystickBase.x; var dy = y - joystickBase.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 100) { dx = dx / distance * 100; dy = dy / distance * 100; } joystickHandle.x = joystickBase.x + dx; joystickHandle.y = joystickBase.y + dy; } }; game.up = function (x, y, obj) { isDragging = false; joystickHandle.x = joystickBase.x; joystickHandle.y = joystickBase.y; }; // Main game loop game.update = function () { // Ship movement var shipDX = 0; var shipDY = 0; if (isDragging) { var dx = joystickHandle.x - joystickBase.x; var dy = joystickHandle.y - joystickBase.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 10) { var effectiveSpeed = ship.speed + ship.boostSpeed; shipDX = dx / 100 * effectiveSpeed; shipDY = dy / 100 * effectiveSpeed; ship.rotation = Math.atan2(dy, dx) + Math.PI / 2; // Create boost particles when boosting if (ship.boostSpeed > 0 && LK.ticks % 2 === 0) { createBoostParticle(); } } } // Track total distance traveled totalDistance += Math.sqrt(shipDX * shipDX + shipDY * shipDY); // Update camera to follow ship movement camera.x += shipDX; camera.y += shipDY; // Move all world objects opposite to ship movement to create camera effect for (var i = 0; i < stars.length; i++) { stars[i].x -= shipDX; stars[i].y -= shipDY; } for (var i = 0; i < npcs.length; i++) { npcs[i].x -= shipDX; npcs[i].y -= shipDY; } for (var i = 0; i < pirates.length; i++) { pirates[i].x -= shipDX; pirates[i].y -= shipDY; } for (var i = 0; i < coins.length; i++) { coins[i].x -= shipDX; coins[i].y -= shipDY; } for (var i = 0; i < resources.length; i++) { resources[i].x -= shipDX; resources[i].y -= shipDY; } for (var i = 0; i < bullets.length; i++) { bullets[i].x -= shipDX; bullets[i].y -= shipDY; } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].x -= shipDX; enemyBullets[i].y -= shipDY; } for (var i = 0; i < asteroids.length; i++) { asteroids[i].x -= shipDX; asteroids[i].y -= shipDY; } for (var i = 0; i < upgradeStations.length; i++) { upgradeStations[i].x -= shipDX; upgradeStations[i].y -= shipDY; } for (var i = 0; i < boostParticles.length; i++) { boostParticles[i].x -= shipDX; boostParticles[i].y -= shipDY; } for (var i = 0; i < explosions.length; i++) { explosions[i].x -= shipDX; explosions[i].y -= shipDY; } // Auto fire at very close pirates or asteroids // Saldırı mesafesi %10 arttırıldı (200 -> 220) var ATTACK_RANGE = 220; if (LK.ticks - ship.lastFire > ship.fireRate && (pirates.length > 0 || asteroids.length > 0)) { // Find nearest pirate or asteroid within 220 pixels var nearestTarget = null; var nearestDistance = Infinity; var isPirate = false; // Check pirates for (var i = 0; i < pirates.length; i++) { var dist = Math.sqrt(Math.pow(pirates[i].x - ship.x, 2) + Math.pow(pirates[i].y - ship.y, 2)); if (dist < ATTACK_RANGE && dist < nearestDistance) { nearestDistance = dist; nearestTarget = pirates[i]; isPirate = true; } } // Check asteroids for (var i = 0; i < asteroids.length; i++) { var dist = Math.sqrt(Math.pow(asteroids[i].x - ship.x, 2) + Math.pow(asteroids[i].y - ship.y, 2)); if (dist < ATTACK_RANGE && dist < nearestDistance) { nearestDistance = dist; nearestTarget = asteroids[i]; isPirate = false; } } if (nearestTarget) { var bullet = new Bullet(); bullet.x = ship.x; bullet.y = ship.y; var angle = Math.atan2(nearestTarget.y - ship.y, nearestTarget.x - ship.x); bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); bullet.rotation = angle + Math.PI / 2; bullets.push(bullet); game.addChild(bullet); ship.lastFire = LK.ticks; LK.getSound('shoot').play(); } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); bullets.splice(i, 1); continue; } // Check collision with pirates for (var j = pirates.length - 1; j >= 0; j--) { if (bullet.intersects(pirates[j])) { pirates[j].takeDamage(bullet.damage); if (pirates[j].health <= 0) { enemiesKilled++; createExplosion(pirates[j].x, pirates[j].y); // Drop loot var coin = new Coin(); coin.x = pirates[j].x; coin.y = pirates[j].y; coin.value = coin.value * (1 + Math.floor(waveNumber / 3)); coins.push(coin); game.addChild(coin); if (Math.random() < 0.3) { var resource = new Resource(); resource.x = pirates[j].x + (Math.random() - 0.5) * 50; resource.y = pirates[j].y + (Math.random() - 0.5) * 50; resources.push(resource); game.addChild(resource); } // Give 1-3 EXP for each pirate killed var pirateExp = 1 + Math.floor(Math.random() * 3); playerEXP += pirateExp; // Level up if enough EXP while (playerEXP >= expToNext(playerLevel)) { playerEXP -= expToNext(playerLevel); playerLevel++; LK.effects.flashObject(ship, 0x00ffcc, 800); } // Update UI after EXP gain updateUI(); pirates[j].destroy(); pirates.splice(j, 1); // Check for wave completion if (enemiesKilled >= 10 + waveNumber * 5) { waveNumber++; enemiesKilled = 0; // Spawn upgrade station every 3 waves if (waveNumber % 3 === 0) { spawnUpgradeStation(); } } } bullet.destroy(); bullets.splice(i, 1); LK.getSound('hit').play(); break; } } // Check collision with asteroids for (var j = asteroids.length - 1; j >= 0; j--) { if (bullet.intersects(asteroids[j])) { asteroids[j].takeDamage(bullet.damage); if (asteroids[j].health <= 0) { // Drop multiple resources for (var k = 0; k < asteroids[j].resources; k++) { var resource = new Resource(); resource.x = asteroids[j].x + (Math.random() - 0.5) * 100; resource.y = asteroids[j].y + (Math.random() - 0.5) * 100; resource.amount = Math.floor(Math.random() * 3) + 1; resources.push(resource); game.addChild(resource); } createExplosion(asteroids[j].x, asteroids[j].y); asteroids[j].destroy(); asteroids.splice(j, 1); } bullet.destroy(); bullets.splice(i, 1); LK.getSound('hit').play(); break; } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } if (bullet.intersects(ship)) { ship.takeDamage(bullet.damage); updateUI(); bullet.destroy(); enemyBullets.splice(i, 1); LK.getSound('hit').play(); } } // Update pirates for (var i = 0; i < pirates.length; i++) { var pirate = pirates[i]; if (pirate._healthBar && pirate._healthBar.update) pirate._healthBar.update(); // Update pirate AI var dist = Math.sqrt(Math.pow(ship.x - pirate.x, 2) + Math.pow(ship.y - pirate.y, 2)); // Eğer bir NPC'nin hunt görevi varsa ve bu korsan hedefse, birlikte saldırı efekti var huntedByNPC = false; for (var n = 0; n < npcs.length; n++) { var npc = npcs[n]; if (npc.questType === 'hunt' && npc.questActive && npc.questTarget === pirate && !pirate._destroyed) { huntedByNPC = true; // NPC'nin saldırı animasyonu için efekt if (!pirate._lastHuntFlash || LK.ticks - pirate._lastHuntFlash > 30) { LK.effects.flashObject(pirate, 0xffcccc, 100); pirate._lastHuntFlash = LK.ticks; } // Eğer oyuncu da yakınsa, korsan hem NPC'ye hem oyuncuya saldırabilir var distToNPC = Math.sqrt(Math.pow(npc.x - pirate.x, 2) + Math.pow(npc.y - pirate.y, 2)); if (distToNPC < 200 && dist < 200) { // Rastgele oyuncuya veya NPC'ye saldır var target = Math.random() < 0.5 ? ship : npc; var angle = Math.atan2(target.y - pirate.y, target.x - pirate.x); pirate.x += Math.cos(angle) * pirate.speed; pirate.y += Math.sin(angle) * pirate.speed; pirate.rotation = angle + Math.PI / 2; // Pirate shooting if (LK.ticks - pirate.lastFire > pirate.fireRate) { var bullet = new EnemyBullet(); bullet.x = pirate.x; bullet.y = pirate.y; bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); enemyBullets.push(bullet); game.addChild(bullet); pirate.lastFire = LK.ticks; } continue; } } } // Only chase and attack when very close (within 220 pixels) // Saldırı mesafesi %10 arttırıldı (200 -> 220) if (!huntedByNPC && dist < 220) { // Chase ship when very close var angle = Math.atan2(ship.y - pirate.y, ship.x - pirate.x); pirate.x += Math.cos(angle) * pirate.speed; pirate.y += Math.sin(angle) * pirate.speed; pirate.rotation = angle + Math.PI / 2; // Pirate shooting when very close if (LK.ticks - pirate.lastFire > pirate.fireRate) { var bullet = new EnemyBullet(); bullet.x = pirate.x; bullet.y = pirate.y; bullet.directionX = Math.cos(angle); bullet.directionY = Math.sin(angle); enemyBullets.push(bullet); game.addChild(bullet); pirate.lastFire = LK.ticks; } } if (dist > 2000) { pirate.destroy(); pirates.splice(i, 1); i--; } } // Update NPCs var npcActive = false; for (var i = npcs.length - 1; i >= 0; i--) { var npc = npcs[i]; if (npc._healthBar && npc._healthBar.update) npc._healthBar.update(); // Remove NPCs that are too far away var dist = Math.sqrt(Math.pow(npc.x - ship.x, 2) + Math.pow(npc.y - ship.y, 2)); if (dist > 2500) { npc.destroy(); npcs.splice(i, 1); continue; } // Görev tamamlandıysa, NPC'nin etkileşim mesajı ve durumu güncellensin if (npc.questActive && npc.questProgress === 1 && !npc._questCompleteShown) { // Görev tamamlandı mesajı göster var completeLabel = new Text2("Görev tamamlandı!", { size: 36, fill: 0x00ff99, align: "center" }); completeLabel.anchor.set(0.5, 0.5); completeLabel.x = npc.x; completeLabel.y = npc.y + 110; game.addChild(completeLabel); npc._npcInteractionLabel = completeLabel; npc._npcInteractionLabelExpire = LK.ticks + 120; npc._questCompleteShown = true; // NPC kısa süre dursun npc.pauseUntil = LK.ticks + 120; // NPC'nin questActive'ini pasif yap (tekrar etkileşim olmasın) npc.questActive = false; } // RPG/Adventure: If player is close, show interaction UI if (dist < 180) { npcActive = true; // Remove any previous floating text if (npc._npcText && npc._npcText.parent) { npc._npcText.parent.removeChild(npc._npcText); npc._npcText = null; } var npcMsg = ""; if (game._lastNPCTap !== undefined && game._lastNPCTap + 30 > LK.ticks && game._lastNPC !== npc) { // Player tapped recently, interact var msg = npc.interact(); npcMsg = msg; updateUI(); saveProgress(); game._lastNPC = npc; // Pause NPC for 2 seconds (120 ticks) after interaction npc.pauseUntil = LK.ticks + 120; // Also clear tradeText in GUI tradeText.setText(''); // --- Show floating interaction label under NPC for a short duration --- if (msg && typeof msg === "string" && msg.length > 0) { // Remove previous interaction label if any if (npc._npcInteractionLabel && npc._npcInteractionLabel.parent) { npc._npcInteractionLabel.parent.removeChild(npc._npcInteractionLabel); npc._npcInteractionLabel = null; } var interactionLabel = new Text2(msg.split('\n')[0], { size: 30, fill: 0xffffff, align: "center" }); interactionLabel.anchor.set(0.5, 0); interactionLabel.x = npc.x; interactionLabel.y = npc.y + 70; npc._npcInteractionLabel = interactionLabel; game.addChild(interactionLabel); // Set a timer to remove after 2.5 seconds (150 ticks) npc._npcInteractionLabelExpire = LK.ticks + 150; } // --- Show Accept/Reject quest buttons above the ship if NPC is a quest-giver and quest is not yet accepted --- if (npc.questActive && npc.questType !== 'trade' && npc.questProgress === 0 && !npc._questDecisionPanel) { // Remove any previous quest panel if (game._questDecisionPanel && game._questDecisionPanel.parent) { game._questDecisionPanel.parent.removeChild(game._questDecisionPanel); game._questDecisionPanel = null; } if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) { game._questDecisionAcceptBtn.parent.removeChild(game._questDecisionAcceptBtn); game._questDecisionAcceptBtn = null; } if (game._questDecisionRejectBtn && game._questDecisionRejectBtn.parent) { game._questDecisionRejectBtn.parent.removeChild(game._questDecisionRejectBtn); game._questDecisionRejectBtn = null; } // Panel background var panel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, x: ship.x, y: ship.y - 180, scaleX: 7, scaleY: 2, tint: 0x222244 }); // Quest text var questText = new Text2("Görev: " + (npcMsg ? npcMsg.split('\n')[0] : "Bir görev var!"), { size: 38, fill: 0xffffff, align: "center" }); questText.anchor.set(0.5, 0.5); questText.x = ship.x; questText.y = ship.y - 200; // Accept button var acceptBtn = new Text2("Kabul Et", { size: 44, fill: 0x00ff99, align: "center" }); acceptBtn.anchor.set(0.5, 0.5); acceptBtn.x = ship.x - 100; acceptBtn.y = ship.y - 120; // Reject button var rejectBtn = new Text2("Reddet", { size: 44, fill: 0xff4444, align: "center" }); rejectBtn.anchor.set(0.5, 0.5); rejectBtn.x = ship.x + 100; rejectBtn.y = ship.y - 120; // Add to game game.addChild(panel); game.addChild(questText); game.addChild(acceptBtn); game.addChild(rejectBtn); // Store references for cleanup npc._questDecisionPanel = panel; npc._questDecisionText = questText; npc._questDecisionAcceptBtn = acceptBtn; npc._questDecisionRejectBtn = rejectBtn; game._questDecisionPanel = panel; game._questDecisionAcceptBtn = acceptBtn; game._questDecisionRejectBtn = rejectBtn; game._questDecisionText = questText; game._questDecisionNPC = npc; // Accept/Reject tap logic acceptBtn._isQuestAcceptBtn = true; rejectBtn._isQuestRejectBtn = true; acceptBtn._questNPC = npc; rejectBtn._questNPC = npc; acceptBtn._questType = npc.questType; rejectBtn._questType = npc.questType; } // --- NPC Trade Panel Logic --- if (npc.questType === 'trade' && npc.questActive && !npc.hasTraded) { // Show a trade panel above the NPC with offer and tap-to-trade var offer = npc.rpgTradeOffer; var canTrade = false; var tradeMsg = ""; if (offer.give === 'metal' && playerMetal >= offer.wantAmount) { canTrade = true; tradeMsg = "Trade: Give " + offer.wantAmount + " " + offer.want + " for " + offer.giveAmount + " " + offer.give + " (Tap to confirm)"; } else if (offer.give === 'energy' && playerEnergy >= offer.wantAmount) { canTrade = true; tradeMsg = "Trade: Give " + offer.wantAmount + " " + offer.want + " for " + offer.giveAmount + " " + offer.give + " (Tap to confirm)"; } else { tradeMsg = "Trade: Need " + offer.wantAmount + " " + offer.want + " to trade for " + offer.giveAmount + " " + offer.give; } // Remove previous trade panel if any if (npc._npcTradePanel && npc._npcTradePanel.parent) { npc._npcTradePanel.parent.removeChild(npc._npcTradePanel); npc._npcTradePanel = null; } var tradePanel = new Text2(tradeMsg, { size: 36, fill: canTrade ? 0x00ff99 : 0xff8888, align: "center" }); tradePanel.anchor.set(0.5, 0); tradePanel.x = npc.x; tradePanel.y = npc.y + 80; npc._npcTradePanel = tradePanel; game.addChild(tradePanel); // If tapped again within window, perform trade if (canTrade && game._lastNPCTap !== undefined && game._lastNPCTap + 15 > LK.ticks && game._lastNPCTrade !== npc) { // Actually perform trade if (offer.give === 'metal') { playerMetal -= offer.wantAmount; playerEnergy += offer.giveAmount; } else { playerEnergy -= offer.wantAmount; playerMetal += offer.giveAmount; } npc.hasTraded = true; var expMsg = "EXP +" + (10 + Math.floor(Math.random() * 10)); playerEXP += 10 + Math.floor(Math.random() * 10); updateUI(); saveProgress(); // Show confirmation tradePanel.setText("Trade complete!\n" + expMsg); tradePanel.fill = 0x00ffcc; game._lastNPCTrade = npc; } } else { // Remove trade panel if not trading if (npc._npcTradePanel && npc._npcTradePanel.parent) { npc._npcTradePanel.parent.removeChild(npc._npcTradePanel); npc._npcTradePanel = null; } } } else if (!npc.questActive || npc.questProgress > 0) { npcMsg = npc.rpgName + ": " + (npc.questActive ? "Thank you!" : "Safe travels!"); // Remove trade panel if not trading if (npc._npcTradePanel && npc._npcTradePanel.parent) { npc._npcTradePanel.parent.removeChild(npc._npcTradePanel); npc._npcTradePanel = null; } } else { // Show quest/trade offer if (npc.questType === 'trade') { npcMsg = npc.rpgName + ": Trade? Tap to interact."; } else if (npc.questType === 'delivery') { npcMsg = npc.rpgName + ": Delivery quest! Tap to interact."; } else if (npc.questType === 'explore') { npcMsg = npc.rpgName + ": Exploration quest! Tap to interact."; } else if (npc.questType === 'escort') { npcMsg = npc.rpgName + ": Escort quest! Tap to interact."; } else if (npc.questType === 'hunt') { npcMsg = npc.rpgName + ": Hunt quest! Tap to interact."; } else if (npc.questType === 'puzzle') { npcMsg = npc.rpgName + ": Puzzle quest! Tap to interact."; } // Remove trade panel if not trading if (npc._npcTradePanel && npc._npcTradePanel.parent) { npc._npcTradePanel.parent.removeChild(npc._npcTradePanel); npc._npcTradePanel = null; } } // Show floating text above NPC if (npcMsg) { var npcText = new Text2(npcMsg, { size: 38, fill: 0x00ffcc, align: "center" }); npcText.anchor.set(0.5, 1); npcText.x = npc.x; npcText.y = npc.y - 70; // Remove previous if any if (npc._npcText && npc._npcText.parent) { npc._npcText.parent.removeChild(npc._npcText); } npc._npcText = npcText; game.addChild(npcText); } // Remove tradeText from GUI tradeText.setText(''); } else { // Remove floating text if player is not close if (npc._npcText && npc._npcText.parent) { npc._npcText.parent.removeChild(npc._npcText); npc._npcText = null; } } // Remove quest Accept/Reject panel if player moves away from NPC if (npc._questDecisionPanel && dist >= 220) { if (npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel); if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText); if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn); if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn); npc._questDecisionPanel = null; npc._questDecisionText = null; npc._questDecisionAcceptBtn = null; npc._questDecisionRejectBtn = null; game._questDecisionPanel = null; game._questDecisionAcceptBtn = null; game._questDecisionRejectBtn = null; game._questDecisionText = null; game._questDecisionNPC = null; } // Remove floating interaction label if expired if (npc._npcInteractionLabel && npc._npcInteractionLabelExpire !== undefined && LK.ticks > npc._npcInteractionLabelExpire) { if (npc._npcInteractionLabel.parent) { npc._npcInteractionLabel.parent.removeChild(npc._npcInteractionLabel); } npc._npcInteractionLabel = null; npc._npcInteractionLabelExpire = undefined; } } if (!npcActive) { game._lastNPC = null; } // Update asteroids for (var i = asteroids.length - 1; i >= 0; i--) { var asteroid = asteroids[i]; if (asteroid._healthBar && asteroid._healthBar.update) asteroid._healthBar.update(); var dist = Math.sqrt(Math.pow(asteroid.x - ship.x, 2) + Math.pow(asteroid.y - ship.y, 2)); if (dist > 2500) { asteroid.destroy(); asteroids.splice(i, 1); } } // --- Space Debris Field Event --- // Every 18000 ticks, 10% chance, only one at a time if (!window.debrisField && LK.ticks % 18000 === 0 && Math.random() < 0.1) { var cx = ship.x + (Math.random() - 0.5) * 3000; var cy = ship.y + (Math.random() - 0.5) * 3000; var debris = []; for (var i = 0; i < 15; i++) { var a = new Asteroid(); var angle = Math.random() * Math.PI * 2; var radius = 200 + Math.random() * 200; a.x = cx + Math.cos(angle) * radius; a.y = cy + Math.sin(angle) * radius; a.health = 10 + Math.floor(Math.random() * 20); a.resources = 1 + Math.floor(Math.random() * 3); asteroids.push(a); game.addChild(a); debris.push(a); } var debrisLabel = new Text2("Enkaz Alanı", { size: 36, fill: 0xcccccc, align: "center" }); debrisLabel.anchor.set(0.5, 0); debrisLabel.x = cx; debrisLabel.y = cy + 250; game.addChild(debrisLabel); window.debrisField = { debris: debris, label: debrisLabel, x: cx, y: cy }; } // Remove debris field if all asteroids gone or too far if (window.debrisField) { var allGone = true; for (var i = 0; i < window.debrisField.debris.length; i++) { if (asteroids.indexOf(window.debrisField.debris[i]) !== -1) { allGone = false; break; } } var dist = Math.sqrt(Math.pow(window.debrisField.x - ship.x, 2) + Math.pow(window.debrisField.y - ship.y, 2)); if (allGone || dist > 4000) { if (window.debrisField.label && window.debrisField.label.parent) window.debrisField.label.parent.removeChild(window.debrisField.label); window.debrisField = null; } else { // Keep label above field if (window.debrisField.label) { window.debrisField.label.x = window.debrisField.x; window.debrisField.label.y = window.debrisField.y + 250; } } } // Update upgrade stations for (var i = upgradeStations.length - 1; i >= 0; i--) { var station = upgradeStations[i]; var dist = Math.sqrt(Math.pow(station.x - ship.x, 2) + Math.pow(station.y - ship.y, 2)); if (dist < 100 && playerCoins >= 100) { // Apply random upgrade var upgrade = station.upgrades[Math.floor(Math.random() * station.upgrades.length)]; if (upgrade.name === 'health' && playerMetal >= (upgrade.metalCost || 0)) { ship.maxHealth += 20; ship.health = ship.maxHealth; playerCoins -= upgrade.cost; playerMetal -= upgrade.metalCost || 0; } else if (upgrade.name === 'shield' && playerMetal >= (upgrade.metalCost || 0)) { ship.maxShield += 10; ship.shield = ship.maxShield; playerCoins -= upgrade.cost; playerMetal -= upgrade.metalCost || 0; } else if (upgrade.name === 'damage' && playerEnergy >= (upgrade.energyCost || 0)) { ship.damage += 5; playerCoins -= upgrade.cost; playerEnergy -= upgrade.energyCost || 0; } else if (upgrade.name === 'speed' && playerEnergy >= (upgrade.energyCost || 0)) { ship.speed += 1; playerCoins -= upgrade.cost; playerEnergy -= upgrade.energyCost || 0; } if (LK.getSound('upgrade')) { LK.getSound('upgrade').play(); } updateUI(); saveProgress(); station.destroy(); upgradeStations.splice(i, 1); } if (dist > 3000) { station.destroy(); upgradeStations.splice(i, 1); } } // Update boost particles for (var i = boostParticles.length - 1; i >= 0; i--) { var particle = boostParticles[i]; particle.x += particle.vx; particle.y += particle.vy; particle.life--; particle.alpha = particle.life / 20; if (particle.life <= 0) { particle.destroy(); boostParticles.splice(i, 1); } } // Update explosion particles for (var i = explosions.length - 1; i >= 0; i--) { var particle = explosions[i]; particle.x += particle.vx; particle.y += particle.vy; particle.vx *= 0.9; particle.vy *= 0.9; particle.life--; particle.alpha = particle.life / 30; particle.scaleX = particle.scaleY = 1 + (30 - particle.life) / 10; if (particle.life <= 0) { particle.destroy(); explosions.splice(i, 1); } } // Collect items for (var i = coins.length - 1; i >= 0; i--) { if (coins[i].intersects(ship)) { playerCoins += coins[i].value; coins[i].destroy(); coins.splice(i, 1); LK.getSound('collect').play(); updateUI(); saveProgress(); } } for (var i = resources.length - 1; i >= 0; i--) { if (resources[i].intersects(ship)) { if (resources[i].type === 'metal') { playerMetal += resources[i].amount; } else { playerEnergy += resources[i].amount; } resources[i].destroy(); resources.splice(i, 1); LK.getSound('collect').play(); updateUI(); saveProgress(); } } // Update stars for (var i = stars.length - 1; i >= 0; i--) { var dist = Math.sqrt(Math.pow(stars[i].x - ship.x, 2) + Math.pow(stars[i].y - ship.y, 2)); if (dist > 2000) { stars[i].destroy(); stars.splice(i, 1); } } // Update pirate bases for (var i = pirateBases.length - 1; i >= 0; i--) { var base = pirateBases[i]; if (base.update) base.update(); var dist = Math.sqrt(Math.pow(base.x - ship.x, 2) + Math.pow(base.y - ship.y, 2)); // Remove base if too far or destroyed if (dist > 3500 || base._destroyed) { if (base._healthBar && base._healthBar.parent) base._healthBar.parent.removeChild(base._healthBar); base.destroy(); pirateBases.splice(i, 1); } } // Update black holes for (var i = blackHoles.length - 1; i >= 0; i--) { var bh = blackHoles[i]; if (bh.update) bh.update(); var dist = Math.sqrt(Math.pow(bh.x - ship.x, 2) + Math.pow(bh.y - ship.y, 2)); if (dist > 3000) { bh.destroy(); blackHoles.splice(i, 1); } } // Update wormholes for (var i = wormholes.length - 1; i >= 0; i--) { var wh = wormholes[i]; if (wh.update) wh.update(); var dist = Math.sqrt(Math.pow(wh.x - ship.x, 2) + Math.pow(wh.y - ship.y, 2)); if (dist > 3000) { wh.destroy(); wormholes.splice(i, 1); } } // Update trade stations (RPG/ticaret) var tradeActive = false; for (var i = tradeStations.length - 1; i >= 0; i--) { var ts = tradeStations[i]; if (ts.update) ts.update(); var dist = Math.sqrt(Math.pow(ts.x - ship.x, 2) + Math.pow(ts.y - ship.y, 2)); if (dist < 180) { tradeActive = true; // Show trade offer if (ts.specialOffer && ts.specialUpgrade) { tradeText.setText('Special: ' + ts.specialUpgrade.label + ' for ' + ts.specialUpgrade.cost + ' coins\n(Tap to buy)'); // Buy special upgrade on tap if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) { if (playerCoins >= ts.specialUpgrade.cost) { playerCoins -= ts.specialUpgrade.cost; if (ts.specialUpgrade.name === 'maxHealth') { ship.maxHealth += 30; ship.health = ship.maxHealth; } else if (ts.specialUpgrade.name === 'maxShield') { ship.maxShield += 20; ship.shield = ship.maxShield; } else if (ts.specialUpgrade.name === 'damage') { ship.damage += 5; } else if (ts.specialUpgrade.name === 'speed') { ship.speed += 1; } LK.effects.flashObject(ship, 0x00ff99, 400); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Upgrade purchased!'); game._lastTradeStation = null; break; } else { tradeText.setText('Not enough coins!'); } } } else if (ts.offerType === 'buy') { tradeText.setText('Trade: Sell ' + ts.amount + ' ' + ts.resourceType + ' for ' + ts.price + ' coins\n(Tap to sell)'); // Sell resource on tap if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) { if (ts.resourceType === 'metal' && playerMetal >= ts.amount) { playerMetal -= ts.amount; playerCoins += ts.price; LK.effects.flashObject(ship, 0x00ff99, 200); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Sold!'); game._lastTradeStation = null; break; } else if (ts.resourceType === 'energy' && playerEnergy >= ts.amount) { playerEnergy -= ts.amount; playerCoins += ts.price; LK.effects.flashObject(ship, 0x00ff99, 200); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Sold!'); game._lastTradeStation = null; break; } else { tradeText.setText('Not enough ' + ts.resourceType + '!'); } } } else if (ts.offerType === 'sell') { tradeText.setText('Trade: Buy ' + ts.amount + ' ' + ts.resourceType + ' for ' + ts.price + ' coins\n(Tap to buy)'); // Buy resource on tap if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) { if (playerCoins >= ts.price) { playerCoins -= ts.price; if (ts.resourceType === 'metal') { playerMetal += ts.amount; } else { playerEnergy += ts.amount; } LK.effects.flashObject(ship, 0x00ff99, 200); updateUI(); saveProgress(); ts.destroy(); tradeStations.splice(i, 1); tradeText.setText('Purchased!'); game._lastTradeStation = null; break; } else { tradeText.setText('Not enough coins!'); } } } game._lastTradeStation = ts; } if (dist > 2500) { ts.destroy(); tradeStations.splice(i, 1); } } if (!tradeActive) { tradeText.setText(''); game._lastTradeStation = null; } // Spawn entities (reduced by 70%) if (LK.ticks % 100 === 0) { if (Math.random() < 0.5) { // 50% chance spawnStar(); } } // --- Anomaly Events: Space Storm, Nebula, Time Warp --- // Only one anomaly at a time, random chance every 9000 ticks if (!window.activeAnomaly && LK.ticks % 9000 === 0 && Math.random() < 0.33) { var anomalyType = Math.random(); if (anomalyType < 0.34) { // Space Storm: disables boost and slows ship for 20 seconds window.activeAnomaly = "storm"; window.anomalyExpire = LK.ticks + 1200; ship.speed = Math.max(2, ship.speed - 2); ship.boostCooldown = 9999; var stormLabel = new Text2("UZAY FIRTINASI! Hız ve boost devre dışı!", { size: 44, fill: 0x00ffff, align: "center" }); stormLabel.anchor.set(0.5, 0.5); stormLabel.x = ship.x; stormLabel.y = ship.y - 200; game.addChild(stormLabel); window.anomalyLabel = stormLabel; } else if (anomalyType < 0.67) { // Nebula: disables auto-fire and reduces vision (star alpha) window.activeAnomaly = "nebula"; window.anomalyExpire = LK.ticks + 1200; window._oldStarAlpha = []; for (var i = 0; i < stars.length; i++) { window._oldStarAlpha[i] = stars[i].children[0].alpha; stars[i].children[0].alpha = 0.1; } window._oldAutoFire = ship.autoFireDisabled; ship.autoFireDisabled = true; var nebulaLabel = new Text2("NEBULA! Otomatik ateş ve görüş kısıtlı!", { size: 44, fill: 0xcc99ff, align: "center" }); nebulaLabel.anchor.set(0.5, 0.5); nebulaLabel.x = ship.x; nebulaLabel.y = ship.y - 200; game.addChild(nebulaLabel); window.anomalyLabel = nebulaLabel; } else { // Time Warp: all pirates/asteroids move double speed, player gets double EXP window.activeAnomaly = "timewarp"; window.anomalyExpire = LK.ticks + 1200; for (var i = 0; i < pirates.length; i++) pirates[i].speed *= 2; for (var i = 0; i < asteroids.length; i++) asteroids[i].vx *= 2, asteroids[i].vy *= 2; window._expMultiplier = 2; var warpLabel = new Text2("ZAMAN YAMULMASI! Düşmanlar hızlı, EXP x2!", { size: 44, fill: 0xffcc00, align: "center" }); warpLabel.anchor.set(0.5, 0.5); warpLabel.x = ship.x; warpLabel.y = ship.y - 200; game.addChild(warpLabel); window.anomalyLabel = warpLabel; } } // Anomaly expire logic if (window.activeAnomaly && LK.ticks > window.anomalyExpire) { if (window.activeAnomaly === "storm") { ship.speed = Math.min(ship.speed + 2, 10); ship.boostCooldown = 0; } else if (window.activeAnomaly === "nebula") { for (var i = 0; i < stars.length; i++) { if (window._oldStarAlpha && window._oldStarAlpha[i] !== undefined) stars[i].children[0].alpha = window._oldStarAlpha[i]; } ship.autoFireDisabled = window._oldAutoFire || false; } else if (window.activeAnomaly === "timewarp") { for (var i = 0; i < pirates.length; i++) pirates[i].speed /= 2; for (var i = 0; i < asteroids.length; i++) asteroids[i].vx /= 2, asteroids[i].vy /= 2; window._expMultiplier = 1; } if (window.anomalyLabel && window.anomalyLabel.parent) window.anomalyLabel.parent.removeChild(window.anomalyLabel); window.activeAnomaly = null; window.anomalyExpire = null; window.anomalyLabel = null; } // Spawn black holes occasionally if (LK.ticks % 3600 === 0 && Math.random() < 0.6) { spawnBlackHole(); } // Spawn wormholes occasionally if (LK.ticks % 4200 === 0 && Math.random() < 0.6) { spawnWormhole(); } // Spawn trade stations occasionally (RPG/ticaret) if (LK.ticks % 4800 === 0 && Math.random() < 0.6) { spawnTradeStation(); } // Spawn pirate bases occasionally if (LK.ticks % 6000 === 0 && Math.random() < 0.5 && pirateBases.length < 3) { spawnPirateBase(); } if (LK.ticks % 900 === 0) { var spawnRoll = Math.random(); if (spawnRoll < 0.15) { // 15% chance (pirates reduced by 85%) spawnPirate(); } else if (spawnRoll < 0.31) { // 16% chance (NPCs increased by 10%) spawnNPC(); } else if (spawnRoll < 0.33) { // 2% chance // Spawn multiple entities occasionally spawnPirate(); spawnNPC(); } } // Spawn asteroids (reduced by 70%) if (LK.ticks % 1500 === 0) { if (Math.random() < 0.5) { // 50% chance spawnAsteroid(); } } // --- Derelict Ship Event --- // Every 12000 ticks, 20% chance, only one at a time if (!window.derelictShip && LK.ticks % 12000 === 0 && Math.random() < 0.2) { var derelict = LK.getAsset('ship', { anchorX: 0.5, anchorY: 0.5, x: ship.x + (Math.random() - 0.5) * 2000, y: ship.y + (Math.random() - 0.5) * 2000, tint: 0x888888, scaleX: 1.2, scaleY: 1.2, alpha: 0.7 }); derelict._isDerelict = true; derelict._loot = { coins: 50 + Math.floor(Math.random() * 100), metal: 5 + Math.floor(Math.random() * 10), energy: 5 + Math.floor(Math.random() * 10) }; derelict._label = new Text2("Terkedilmiş Gemi", { size: 32, fill: 0xcccccc, align: "center" }); derelict._label.anchor.set(0.5, 0); derelict._label.x = derelict.x; derelict._label.y = derelict.y + 70; game.addChild(derelict); game.addChild(derelict._label); window.derelictShip = derelict; } // Derelict ship interaction if (window.derelictShip) { var d = window.derelictShip; var dist = Math.sqrt(Math.pow(d.x - ship.x, 2) + Math.pow(d.y - ship.y, 2)); if (dist < 120) { // Collect loot playerCoins += d._loot.coins; playerMetal += d._loot.metal; playerEnergy += d._loot.energy; var lootLabel = new Text2("Gemi yağmalandı!\n+" + d._loot.coins + " coin, +" + d._loot.metal + " metal, +" + d._loot.energy + " enerji", { size: 36, fill: 0x00ffcc, align: "center" }); lootLabel.anchor.set(0.5, 0.5); lootLabel.x = d.x; lootLabel.y = d.y - 80; game.addChild(lootLabel); if (d.parent) d.parent.removeChild(d); if (d._label && d._label.parent) d._label.parent.removeChild(d._label); window.derelictShip = null; updateUI(); saveProgress(); // Remove loot label after 2 seconds (function (lbl) { var expire = LK.ticks + 120; var removeLootLabel = function removeLootLabel() { if (LK.ticks > expire && lbl.parent) { lbl.parent.removeChild(lbl); game.update = origUpdate; } }; var origUpdate = game.update; game.update = function () { removeLootLabel(); if (origUpdate) origUpdate.apply(game, arguments); }; })(lootLabel); } else if (dist > 3000) { if (d.parent) d.parent.removeChild(d); if (d._label && d._label.parent) d._label.parent.removeChild(d._label); window.derelictShip = null; } else { // Keep label above derelict if (d._label) { d._label.x = d.x; d._label.y = d.y + 70; } } } // Wave-based pirate spawning if (LK.ticks % (180 - Math.min(waveNumber * 10, 100)) === 0) { var piratesInWave = 1 + Math.floor(waveNumber / 2); for (var j = 0; j < piratesInWave; j++) { spawnPirate(); } } // --- Distress Signal Event --- // Every 15000 ticks, 15% chance, only one at a time if (!window.distressEvent && LK.ticks % 15000 === 0 && Math.random() < 0.15) { var sx = ship.x + (Math.random() - 0.5) * 2500; var sy = ship.y + (Math.random() - 0.5) * 2500; var signal = LK.getAsset('star', { anchorX: 0.5, anchorY: 0.5, x: sx, y: sy, tint: 0xff00ff, scaleX: 4, scaleY: 4, alpha: 0.8 }); var label = new Text2("İmdat Sinyali", { size: 36, fill: 0xff00ff, align: "center" }); label.anchor.set(0.5, 0); label.x = sx; label.y = sy + 70; game.addChild(signal); game.addChild(label); window.distressEvent = { signal: signal, label: label, x: sx, y: sy, state: "waiting" }; } // Distress event logic if (window.distressEvent) { var e = window.distressEvent; var dist = Math.sqrt(Math.pow(e.x - ship.x, 2) + Math.pow(e.y - ship.y, 2)); if (e.state === "waiting" && dist < 120) { // Show choice: rescue or ignore (ambush possibility) if (!e.panel) { var panel = LK.getAsset('resource', { anchorX: 0.5, anchorY: 0.5, x: e.x, y: e.y - 180, scaleX: 7, scaleY: 2, tint: 0x222244 }); var text = new Text2("İmdat sinyali! Yardım et veya uzaklaş?", { size: 38, fill: 0xffffff, align: "center" }); text.anchor.set(0.5, 0.5); text.x = e.x; text.y = e.y - 200; var helpBtn = new Text2("Yardım Et", { size: 44, fill: 0x00ff99, align: "center" }); helpBtn.anchor.set(0.5, 0.5); helpBtn.x = e.x - 100; helpBtn.y = e.y - 120; var ignoreBtn = new Text2("Uzaklaş", { size: 44, fill: 0xff4444, align: "center" }); ignoreBtn.anchor.set(0.5, 0.5); ignoreBtn.x = e.x + 100; ignoreBtn.y = e.y - 120; game.addChild(panel); game.addChild(text); game.addChild(helpBtn); game.addChild(ignoreBtn); e.panel = panel; e.text = text; e.helpBtn = helpBtn; e.ignoreBtn = ignoreBtn; helpBtn._isDistressHelp = true; ignoreBtn._isDistressIgnore = true; helpBtn._distressEvent = e; ignoreBtn._distressEvent = e; } // Tap logic for help/ignore if (game._lastDistressTap !== e && game._lastDistressTapTick !== undefined && game._lastDistressTapTick + 30 > LK.ticks) { var tapX = game._lastDistressTapX, tapY = game._lastDistressTapY; if (tapX > e.helpBtn.x - 90 && tapX < e.helpBtn.x + 90 && tapY > e.helpBtn.y - 40 && tapY < e.helpBtn.y + 40) { // Help: 70% chance for reward, 30% ambush if (Math.random() < 0.7) { var reward = 100 + Math.floor(Math.random() * 100); playerCoins += reward; var msg = new Text2("Kurtarılan gemi! Ödül: " + reward + " coin", { size: 36, fill: 0x00ffcc, align: "center" }); msg.anchor.set(0.5, 0.5); msg.x = e.x; msg.y = e.y - 80; game.addChild(msg); updateUI(); saveProgress(); } else { // Ambush: spawn 3 pirates for (var i = 0; i < 3; i++) { var pirate = new Pirate(); pirate.x = e.x + (Math.random() - 0.5) * 100; pirate.y = e.y + (Math.random() - 0.5) * 100; pirates.push(pirate); game.addChild(pirate); } var msg = new Text2("Pusu! Korsanlar saldırıyor!", { size: 36, fill: 0xff4444, align: "center" }); msg.anchor.set(0.5, 0.5); msg.x = e.x; msg.y = e.y - 80; game.addChild(msg); } // Clean up if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal); if (e.label && e.label.parent) e.label.parent.removeChild(e.label); if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel); if (e.text && e.text.parent) e.text.parent.removeChild(e.text); if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn); if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn); window.distressEvent = null; } else if (tapX > e.ignoreBtn.x - 90 && tapX < e.ignoreBtn.x + 90 && tapY > e.ignoreBtn.y - 40 && tapY < e.ignoreBtn.y + 40) { // Ignore: nothing happens, clean up if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal); if (e.label && e.label.parent) e.label.parent.removeChild(e.label); if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel); if (e.text && e.text.parent) e.text.parent.removeChild(e.text); if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn); if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn); window.distressEvent = null; } game._lastDistressTap = e; } } else if (dist > 3000) { if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal); if (e.label && e.label.parent) e.label.parent.removeChild(e.label); if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel); if (e.text && e.text.parent) e.text.parent.removeChild(e.text); if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn); if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn); window.distressEvent = null; } else { // Keep label above signal if (e.label) { e.label.x = e.x; e.label.y = e.y + 70; } } } // Boss wave every 5 waves if (waveNumber > 0 && waveNumber % 5 === 0 && pirates.length === 0) { var bossPirate = new Pirate(); bossPirate.x = ship.x + 1000; bossPirate.y = ship.y; // Level range: wave 1 => 1-3, wave 2 => 3-5, wave 3 => 5-7, etc. var minLevel = 1 + waveNumber * 2; var maxLevel = minLevel + 2; bossPirate.level = minLevel + Math.floor(Math.random() * (maxLevel - minLevel + 1)); bossPirate.health = 200 + (bossPirate.level - 1) * 20; bossPirate.damage = 10 + Math.floor(bossPirate.level * 1.5); bossPirate.defense = 2 + Math.floor(bossPirate.level * 1.2); bossPirate.loot = 200 + bossPirate.level * 50; bossPirate.speed = 3; var bossGraphics = bossPirate.children[0]; bossGraphics.tint = 0xff00ff; bossGraphics.scaleX = 2; bossGraphics.scaleY = 2; pirates.push(bossPirate); game.addChild(bossPirate); } // Update score LK.setScore(playerCoins + questsCompleted * 100 + enemiesKilled * 10 + Math.floor(totalDistance / 100)); if (ship._healthBar && ship._healthBar.update) ship._healthBar.update(); updateUI(); // Update coordinateText with current ship coordinates (rounded) in real time to the left of waveText if (typeof coordinateText !== "undefined" && ship && typeof waveText !== "undefined") { // Show the actual current coordinates of the ship coordinateText.setText('X: ' + Math.round(ship.x) + ' Y: ' + Math.round(ship.y)); // Always keep coordinateText to the left of waveText, and keep size 30% smaller than expText coordinateText.size = Math.round(expText.size * 0.7); coordinateText.x = waveText.x - waveText.width - 30; coordinateText.y = waveText.y + waveText.height / 2; } };
===================================================================
--- original.js
+++ change.js
@@ -2118,8 +2118,14 @@
game._lastNPCTap = LK.ticks;
break;
}
}
+ // --- Distress event tap detection ---
+ if (window.distressEvent && window.distressEvent.helpBtn && window.distressEvent.ignoreBtn) {
+ game._lastDistressTapTick = LK.ticks;
+ game._lastDistressTapX = x;
+ game._lastDistressTapY = y;
+ }
}
};
game.move = function (x, y, obj) {
if (isDragging) {
@@ -2710,8 +2716,63 @@
asteroid.destroy();
asteroids.splice(i, 1);
}
}
+ // --- Space Debris Field Event ---
+ // Every 18000 ticks, 10% chance, only one at a time
+ if (!window.debrisField && LK.ticks % 18000 === 0 && Math.random() < 0.1) {
+ var cx = ship.x + (Math.random() - 0.5) * 3000;
+ var cy = ship.y + (Math.random() - 0.5) * 3000;
+ var debris = [];
+ for (var i = 0; i < 15; i++) {
+ var a = new Asteroid();
+ var angle = Math.random() * Math.PI * 2;
+ var radius = 200 + Math.random() * 200;
+ a.x = cx + Math.cos(angle) * radius;
+ a.y = cy + Math.sin(angle) * radius;
+ a.health = 10 + Math.floor(Math.random() * 20);
+ a.resources = 1 + Math.floor(Math.random() * 3);
+ asteroids.push(a);
+ game.addChild(a);
+ debris.push(a);
+ }
+ var debrisLabel = new Text2("Enkaz Alanı", {
+ size: 36,
+ fill: 0xcccccc,
+ align: "center"
+ });
+ debrisLabel.anchor.set(0.5, 0);
+ debrisLabel.x = cx;
+ debrisLabel.y = cy + 250;
+ game.addChild(debrisLabel);
+ window.debrisField = {
+ debris: debris,
+ label: debrisLabel,
+ x: cx,
+ y: cy
+ };
+ }
+ // Remove debris field if all asteroids gone or too far
+ if (window.debrisField) {
+ var allGone = true;
+ for (var i = 0; i < window.debrisField.debris.length; i++) {
+ if (asteroids.indexOf(window.debrisField.debris[i]) !== -1) {
+ allGone = false;
+ break;
+ }
+ }
+ var dist = Math.sqrt(Math.pow(window.debrisField.x - ship.x, 2) + Math.pow(window.debrisField.y - ship.y, 2));
+ if (allGone || dist > 4000) {
+ if (window.debrisField.label && window.debrisField.label.parent) window.debrisField.label.parent.removeChild(window.debrisField.label);
+ window.debrisField = null;
+ } else {
+ // Keep label above field
+ if (window.debrisField.label) {
+ window.debrisField.label.x = window.debrisField.x;
+ window.debrisField.label.y = window.debrisField.y + 250;
+ }
+ }
+ }
// Update upgrade stations
for (var i = upgradeStations.length - 1; i >= 0; i--) {
var station = upgradeStations[i];
var dist = Math.sqrt(Math.pow(station.x - ship.x, 2) + Math.pow(station.y - ship.y, 2));
@@ -2951,8 +3012,88 @@
// 50% chance
spawnStar();
}
}
+ // --- Anomaly Events: Space Storm, Nebula, Time Warp ---
+ // Only one anomaly at a time, random chance every 9000 ticks
+ if (!window.activeAnomaly && LK.ticks % 9000 === 0 && Math.random() < 0.33) {
+ var anomalyType = Math.random();
+ if (anomalyType < 0.34) {
+ // Space Storm: disables boost and slows ship for 20 seconds
+ window.activeAnomaly = "storm";
+ window.anomalyExpire = LK.ticks + 1200;
+ ship.speed = Math.max(2, ship.speed - 2);
+ ship.boostCooldown = 9999;
+ var stormLabel = new Text2("UZAY FIRTINASI! Hız ve boost devre dışı!", {
+ size: 44,
+ fill: 0x00ffff,
+ align: "center"
+ });
+ stormLabel.anchor.set(0.5, 0.5);
+ stormLabel.x = ship.x;
+ stormLabel.y = ship.y - 200;
+ game.addChild(stormLabel);
+ window.anomalyLabel = stormLabel;
+ } else if (anomalyType < 0.67) {
+ // Nebula: disables auto-fire and reduces vision (star alpha)
+ window.activeAnomaly = "nebula";
+ window.anomalyExpire = LK.ticks + 1200;
+ window._oldStarAlpha = [];
+ for (var i = 0; i < stars.length; i++) {
+ window._oldStarAlpha[i] = stars[i].children[0].alpha;
+ stars[i].children[0].alpha = 0.1;
+ }
+ window._oldAutoFire = ship.autoFireDisabled;
+ ship.autoFireDisabled = true;
+ var nebulaLabel = new Text2("NEBULA! Otomatik ateş ve görüş kısıtlı!", {
+ size: 44,
+ fill: 0xcc99ff,
+ align: "center"
+ });
+ nebulaLabel.anchor.set(0.5, 0.5);
+ nebulaLabel.x = ship.x;
+ nebulaLabel.y = ship.y - 200;
+ game.addChild(nebulaLabel);
+ window.anomalyLabel = nebulaLabel;
+ } else {
+ // Time Warp: all pirates/asteroids move double speed, player gets double EXP
+ window.activeAnomaly = "timewarp";
+ window.anomalyExpire = LK.ticks + 1200;
+ for (var i = 0; i < pirates.length; i++) pirates[i].speed *= 2;
+ for (var i = 0; i < asteroids.length; i++) asteroids[i].vx *= 2, asteroids[i].vy *= 2;
+ window._expMultiplier = 2;
+ var warpLabel = new Text2("ZAMAN YAMULMASI! Düşmanlar hızlı, EXP x2!", {
+ size: 44,
+ fill: 0xffcc00,
+ align: "center"
+ });
+ warpLabel.anchor.set(0.5, 0.5);
+ warpLabel.x = ship.x;
+ warpLabel.y = ship.y - 200;
+ game.addChild(warpLabel);
+ window.anomalyLabel = warpLabel;
+ }
+ }
+ // Anomaly expire logic
+ if (window.activeAnomaly && LK.ticks > window.anomalyExpire) {
+ if (window.activeAnomaly === "storm") {
+ ship.speed = Math.min(ship.speed + 2, 10);
+ ship.boostCooldown = 0;
+ } else if (window.activeAnomaly === "nebula") {
+ for (var i = 0; i < stars.length; i++) {
+ if (window._oldStarAlpha && window._oldStarAlpha[i] !== undefined) stars[i].children[0].alpha = window._oldStarAlpha[i];
+ }
+ ship.autoFireDisabled = window._oldAutoFire || false;
+ } else if (window.activeAnomaly === "timewarp") {
+ for (var i = 0; i < pirates.length; i++) pirates[i].speed /= 2;
+ for (var i = 0; i < asteroids.length; i++) asteroids[i].vx /= 2, asteroids[i].vy /= 2;
+ window._expMultiplier = 1;
+ }
+ if (window.anomalyLabel && window.anomalyLabel.parent) window.anomalyLabel.parent.removeChild(window.anomalyLabel);
+ window.activeAnomaly = null;
+ window.anomalyExpire = null;
+ window.anomalyLabel = null;
+ }
// Spawn black holes occasionally
if (LK.ticks % 3600 === 0 && Math.random() < 0.6) {
spawnBlackHole();
}
@@ -2989,15 +3130,257 @@
// 50% chance
spawnAsteroid();
}
}
+ // --- Derelict Ship Event ---
+ // Every 12000 ticks, 20% chance, only one at a time
+ if (!window.derelictShip && LK.ticks % 12000 === 0 && Math.random() < 0.2) {
+ var derelict = LK.getAsset('ship', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: ship.x + (Math.random() - 0.5) * 2000,
+ y: ship.y + (Math.random() - 0.5) * 2000,
+ tint: 0x888888,
+ scaleX: 1.2,
+ scaleY: 1.2,
+ alpha: 0.7
+ });
+ derelict._isDerelict = true;
+ derelict._loot = {
+ coins: 50 + Math.floor(Math.random() * 100),
+ metal: 5 + Math.floor(Math.random() * 10),
+ energy: 5 + Math.floor(Math.random() * 10)
+ };
+ derelict._label = new Text2("Terkedilmiş Gemi", {
+ size: 32,
+ fill: 0xcccccc,
+ align: "center"
+ });
+ derelict._label.anchor.set(0.5, 0);
+ derelict._label.x = derelict.x;
+ derelict._label.y = derelict.y + 70;
+ game.addChild(derelict);
+ game.addChild(derelict._label);
+ window.derelictShip = derelict;
+ }
+ // Derelict ship interaction
+ if (window.derelictShip) {
+ var d = window.derelictShip;
+ var dist = Math.sqrt(Math.pow(d.x - ship.x, 2) + Math.pow(d.y - ship.y, 2));
+ if (dist < 120) {
+ // Collect loot
+ playerCoins += d._loot.coins;
+ playerMetal += d._loot.metal;
+ playerEnergy += d._loot.energy;
+ var lootLabel = new Text2("Gemi yağmalandı!\n+" + d._loot.coins + " coin, +" + d._loot.metal + " metal, +" + d._loot.energy + " enerji", {
+ size: 36,
+ fill: 0x00ffcc,
+ align: "center"
+ });
+ lootLabel.anchor.set(0.5, 0.5);
+ lootLabel.x = d.x;
+ lootLabel.y = d.y - 80;
+ game.addChild(lootLabel);
+ if (d.parent) d.parent.removeChild(d);
+ if (d._label && d._label.parent) d._label.parent.removeChild(d._label);
+ window.derelictShip = null;
+ updateUI();
+ saveProgress();
+ // Remove loot label after 2 seconds
+ (function (lbl) {
+ var expire = LK.ticks + 120;
+ var removeLootLabel = function removeLootLabel() {
+ if (LK.ticks > expire && lbl.parent) {
+ lbl.parent.removeChild(lbl);
+ game.update = origUpdate;
+ }
+ };
+ var origUpdate = game.update;
+ game.update = function () {
+ removeLootLabel();
+ if (origUpdate) origUpdate.apply(game, arguments);
+ };
+ })(lootLabel);
+ } else if (dist > 3000) {
+ if (d.parent) d.parent.removeChild(d);
+ if (d._label && d._label.parent) d._label.parent.removeChild(d._label);
+ window.derelictShip = null;
+ } else {
+ // Keep label above derelict
+ if (d._label) {
+ d._label.x = d.x;
+ d._label.y = d.y + 70;
+ }
+ }
+ }
// Wave-based pirate spawning
if (LK.ticks % (180 - Math.min(waveNumber * 10, 100)) === 0) {
var piratesInWave = 1 + Math.floor(waveNumber / 2);
for (var j = 0; j < piratesInWave; j++) {
spawnPirate();
}
}
+ // --- Distress Signal Event ---
+ // Every 15000 ticks, 15% chance, only one at a time
+ if (!window.distressEvent && LK.ticks % 15000 === 0 && Math.random() < 0.15) {
+ var sx = ship.x + (Math.random() - 0.5) * 2500;
+ var sy = ship.y + (Math.random() - 0.5) * 2500;
+ var signal = LK.getAsset('star', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: sx,
+ y: sy,
+ tint: 0xff00ff,
+ scaleX: 4,
+ scaleY: 4,
+ alpha: 0.8
+ });
+ var label = new Text2("İmdat Sinyali", {
+ size: 36,
+ fill: 0xff00ff,
+ align: "center"
+ });
+ label.anchor.set(0.5, 0);
+ label.x = sx;
+ label.y = sy + 70;
+ game.addChild(signal);
+ game.addChild(label);
+ window.distressEvent = {
+ signal: signal,
+ label: label,
+ x: sx,
+ y: sy,
+ state: "waiting"
+ };
+ }
+ // Distress event logic
+ if (window.distressEvent) {
+ var e = window.distressEvent;
+ var dist = Math.sqrt(Math.pow(e.x - ship.x, 2) + Math.pow(e.y - ship.y, 2));
+ if (e.state === "waiting" && dist < 120) {
+ // Show choice: rescue or ignore (ambush possibility)
+ if (!e.panel) {
+ var panel = LK.getAsset('resource', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: e.x,
+ y: e.y - 180,
+ scaleX: 7,
+ scaleY: 2,
+ tint: 0x222244
+ });
+ var text = new Text2("İmdat sinyali! Yardım et veya uzaklaş?", {
+ size: 38,
+ fill: 0xffffff,
+ align: "center"
+ });
+ text.anchor.set(0.5, 0.5);
+ text.x = e.x;
+ text.y = e.y - 200;
+ var helpBtn = new Text2("Yardım Et", {
+ size: 44,
+ fill: 0x00ff99,
+ align: "center"
+ });
+ helpBtn.anchor.set(0.5, 0.5);
+ helpBtn.x = e.x - 100;
+ helpBtn.y = e.y - 120;
+ var ignoreBtn = new Text2("Uzaklaş", {
+ size: 44,
+ fill: 0xff4444,
+ align: "center"
+ });
+ ignoreBtn.anchor.set(0.5, 0.5);
+ ignoreBtn.x = e.x + 100;
+ ignoreBtn.y = e.y - 120;
+ game.addChild(panel);
+ game.addChild(text);
+ game.addChild(helpBtn);
+ game.addChild(ignoreBtn);
+ e.panel = panel;
+ e.text = text;
+ e.helpBtn = helpBtn;
+ e.ignoreBtn = ignoreBtn;
+ helpBtn._isDistressHelp = true;
+ ignoreBtn._isDistressIgnore = true;
+ helpBtn._distressEvent = e;
+ ignoreBtn._distressEvent = e;
+ }
+ // Tap logic for help/ignore
+ if (game._lastDistressTap !== e && game._lastDistressTapTick !== undefined && game._lastDistressTapTick + 30 > LK.ticks) {
+ var tapX = game._lastDistressTapX,
+ tapY = game._lastDistressTapY;
+ if (tapX > e.helpBtn.x - 90 && tapX < e.helpBtn.x + 90 && tapY > e.helpBtn.y - 40 && tapY < e.helpBtn.y + 40) {
+ // Help: 70% chance for reward, 30% ambush
+ if (Math.random() < 0.7) {
+ var reward = 100 + Math.floor(Math.random() * 100);
+ playerCoins += reward;
+ var msg = new Text2("Kurtarılan gemi! Ödül: " + reward + " coin", {
+ size: 36,
+ fill: 0x00ffcc,
+ align: "center"
+ });
+ msg.anchor.set(0.5, 0.5);
+ msg.x = e.x;
+ msg.y = e.y - 80;
+ game.addChild(msg);
+ updateUI();
+ saveProgress();
+ } else {
+ // Ambush: spawn 3 pirates
+ for (var i = 0; i < 3; i++) {
+ var pirate = new Pirate();
+ pirate.x = e.x + (Math.random() - 0.5) * 100;
+ pirate.y = e.y + (Math.random() - 0.5) * 100;
+ pirates.push(pirate);
+ game.addChild(pirate);
+ }
+ var msg = new Text2("Pusu! Korsanlar saldırıyor!", {
+ size: 36,
+ fill: 0xff4444,
+ align: "center"
+ });
+ msg.anchor.set(0.5, 0.5);
+ msg.x = e.x;
+ msg.y = e.y - 80;
+ game.addChild(msg);
+ }
+ // Clean up
+ if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal);
+ if (e.label && e.label.parent) e.label.parent.removeChild(e.label);
+ if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel);
+ if (e.text && e.text.parent) e.text.parent.removeChild(e.text);
+ if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn);
+ if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn);
+ window.distressEvent = null;
+ } else if (tapX > e.ignoreBtn.x - 90 && tapX < e.ignoreBtn.x + 90 && tapY > e.ignoreBtn.y - 40 && tapY < e.ignoreBtn.y + 40) {
+ // Ignore: nothing happens, clean up
+ if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal);
+ if (e.label && e.label.parent) e.label.parent.removeChild(e.label);
+ if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel);
+ if (e.text && e.text.parent) e.text.parent.removeChild(e.text);
+ if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn);
+ if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn);
+ window.distressEvent = null;
+ }
+ game._lastDistressTap = e;
+ }
+ } else if (dist > 3000) {
+ if (e.signal && e.signal.parent) e.signal.parent.removeChild(e.signal);
+ if (e.label && e.label.parent) e.label.parent.removeChild(e.label);
+ if (e.panel && e.panel.parent) e.panel.parent.removeChild(e.panel);
+ if (e.text && e.text.parent) e.text.parent.removeChild(e.text);
+ if (e.helpBtn && e.helpBtn.parent) e.helpBtn.parent.removeChild(e.helpBtn);
+ if (e.ignoreBtn && e.ignoreBtn.parent) e.ignoreBtn.parent.removeChild(e.ignoreBtn);
+ window.distressEvent = null;
+ } else {
+ // Keep label above signal
+ if (e.label) {
+ e.label.x = e.x;
+ e.label.y = e.y + 70;
+ }
+ }
+ }
// Boss wave every 5 waves
if (waveNumber > 0 && waveNumber % 5 === 0 && pirates.length === 0) {
var bossPirate = new Pirate();
bossPirate.x = ship.x + 1000;
Uzay temalı global Cevher ticareti, gerçekçi, Altında "Trade" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı global Cevher ticareti, uzay istasyonu, gerçekçi, Altında "Space Stations" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı global Cevher deposu, uzay kargosu, gerçekçi, Altında "Storage" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı Gemi Geliştirme, Tamirci İstasyonu, gerçekçi, Altında "Upgrade" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı global Achievements, gerçekçi, Altında "Achievements" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı, içi altın dolu kapağı açık kasa, gerçekçi, In-Game asset. High contrast. No shadows
Uzay temalı Spaceship Crew, gerçekçi, Altında "crew" yazsın. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı altın coin, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı Savaş Gemisi, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows
Uzay temalı asteroid, üzerinde cevherler bulunsun, gerçekçi, yazısız üstten görünüm. In-Game asset. High contrast. No shadows