User prompt
Sadece korsan ve Npc sistemi olsun. NPC'ler ile korsan gemileri bazen aralarında savaşsınlar.
User prompt
Bunların ara ara spawn olma sıklığını 3 katına çıkart.
User prompt
Bütün etkinlik, görev ve özel binalar oyundan kaldır veya sil.
User prompt
Bütün oyun alanını, oyun ekranına sığacak şekilde boyutlandır.
User prompt
Gemi oyun ekranının dışına çıkmasın. Kamerayı ona göre hafif konumlandır.
User prompt
Oyun haritasını 10000 kat büyüt
User prompt
Oyun haritasını 100 kat büyüt ve kamerayı gemi takibini bırakmayacak şekilde ayarla.
User prompt
Oyun haritasını 10 kat büyüt.
User prompt
Sonsuz oyun olmasından kaynaklı bu sorun sanırım. Oyun haritasını sınırlandırma yapsan düzelir mi. Bir dene..
User prompt
Aynı şeyler devam ediyor.
User prompt
Özetle bahsettiğin konuların tamamını elden geç. Gerekirse kod düzenle, yaz, sil. Ama şu sorunu çöz.
User prompt
Ekranda oluşan şeylerin, yazıların ve bütün etkinlik, görev gibi şeylerin yenilenme sürecini oluştur. Ekranda çıkar çıkmaz buga giriyor. Ekranda kalıyor.
User prompt
Bu tür etkinlik, görev ve özel binaların, kendilerine özel resim dosyasını oluştur.
User prompt
Bu tür şeyler ekranda benimle birlikte gitmesin. Çıktıkları yerde dolaşsınlar. Bug oluyor gibi. Ekranda sadece görselleri var. Kendileri yok.
User prompt
Herhangi bir etkinlik, özel bina veya görev olduğun, kalan mesafe üzerinde küçük şekilde anlık olarak göstersin.
User prompt
Bütün etkinlikler ve bu son konuştuğumuz görev çeşitleri, oyunda spawn oluyor ama donuyor öylece kalıyor. Ne gidebiliyorum ne gelebiliyorum. Mesafe çok yakın olmasına rağmen.
User prompt
Bütün bu mesafeyi az biraz uzat. Oyun başlayınca dibimde çıkıyor ve herhangi bir etkileşim veya sistemsel değişim olmuyor.
User prompt
Oyunda bulunan bütün kara delik, solucan ve istasyon vb. Ayrıca bütün etkinlikler 400-500px mesafelerde rastgele olmasını sağla.
User prompt
Bunu çözmek için yakında oluşacak şekilde kodları değiştir.
User prompt
Mesafesi bu kadar uzak bir etkinlik veya görev olmasın. Mesafesi sadece spawn mesafesi kadar uzaklıkta olan görev ve etkinlikler olsun. Bu konuda kod üzerinde değişiklik yap.
User prompt
Mini Map yazısını ve butonunu tamamen ekrandan gizle.
User prompt
Bütün etkinlikler, oyun ekranının köşesinde spawn olsun. Ekran dışında spawn olmasın.
User prompt
KILL yazısını tamamen sil çıkmasın.
User prompt
Exp ve rep yazılarını tamamen sil çıkmasın.
User prompt
Game time 2 saniye geçmesine rağmen, rep ve exp yazıları gitmiyor.
/****
* 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
});
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);
// Only floating AI logic, no quests/events/trade
// Add dummy interact method to prevent TypeError
self.interact = function () {
// No interaction for basic NPCs, return empty string
return "";
};
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;
};
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 = [];
var tradeText = null; // No trade text needed
// 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;
// --- MINI MAP OVERLAY DRAW/UPDATE ---
if (window._miniMapVisible) {
// Helper to convert world to mini map
var toMiniMap = function toMiniMap(wx, wy) {
return {
x: mapCenterX + (wx - ship.x) * mapScale,
y: mapCenterY + (wy - ship.y) * mapScale
};
}; // Draw ship
// Create container if not exists
if (!window._miniMapContainer) {
var miniMapContainer = new Container();
// Position: below the ship, centered horizontally
// Ship is at (ship.x, ship.y) in world, but we want minimap in screen coordinates
// Center horizontally, and place just below the ship (ship.y + ship height/2 + margin)
var mapSize = 480;
var marginBelowShip = 80;
var screenW = 2048,
screenH = 2732;
var miniMapX = (screenW - mapSize) / 2;
var miniMapY = Math.min(screenH - mapSize - 40, Math.max(0, ship.y + 100 + marginBelowShip - mapSize / 2));
// Clamp to screen
miniMapY = Math.max(200, Math.min(screenH - mapSize - 40, miniMapY));
miniMapContainer.x = miniMapX;
miniMapContainer.y = miniMapY;
window._miniMapContainer = miniMapContainer;
game.addChild(miniMapContainer);
}
var miniMapContainer = window._miniMapContainer;
// Remove previous elements
for (var i = 0; i < window._miniMapElements.length; i++) {
if (window._miniMapElements[i] && window._miniMapElements[i].parent) {
window._miniMapElements[i].parent.removeChild(window._miniMapElements[i]);
}
}
window._miniMapElements = [];
// Draw background
var bg = LK.getAsset('resource', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 12,
scaleY: 12,
tint: 0x111133,
alpha: 0.92
});
miniMapContainer.addChild(bg);
window._miniMapElements.push(bg);
// Draw border
var border = LK.getAsset('resource', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
scaleX: 12,
scaleY: 12,
tint: 0x00ccff,
alpha: 0.25
});
miniMapContainer.addChild(border);
window._miniMapElements.push(border);
// Mini map covers 6000x6000 px area centered on ship
var mapSize = 480;
var worldSize = 6000;
var halfWorld = worldSize / 2;
var mapScale = mapSize / worldSize;
var mapCenterX = mapSize / 2;
var mapCenterY = mapSize / 2;
var shipPos = toMiniMap(ship.x, ship.y);
var shipDot = LK.getAsset('ship', {
anchorX: 0.5,
anchorY: 0.5,
x: shipPos.x,
y: shipPos.y,
scaleX: 0.3,
scaleY: 0.3,
tint: 0x00ff00,
alpha: 1
});
miniMapContainer.addChild(shipDot);
window._miniMapElements.push(shipDot);
// Draw pirates
for (var i = 0; i < pirates.length; i++) {
var p = pirates[i];
if (p._destroyed) continue;
var pos = toMiniMap(p.x, p.y);
var pirateDot = LK.getAsset('pirate', {
anchorX: 0.5,
anchorY: 0.5,
x: pos.x,
y: pos.y,
scaleX: 0.18,
scaleY: 0.18,
tint: 0xff4444,
alpha: 0.85
});
miniMapContainer.addChild(pirateDot);
window._miniMapElements.push(pirateDot);
}
// Draw NPCs
for (var i = 0; i < npcs.length; i++) {
var n = npcs[i];
var pos = toMiniMap(n.x, n.y);
var npcDot = LK.getAsset('npc', {
anchorX: 0.5,
anchorY: 0.5,
x: pos.x,
y: pos.y,
scaleX: 0.18,
scaleY: 0.18,
tint: 0x00ccff,
alpha: 0.85
});
miniMapContainer.addChild(npcDot);
window._miniMapElements.push(npcDot);
// If NPC has active quest target, draw target marker
if (n.questActive && n.questTarget) {
var tx, ty;
if (n.questType === 'hunt' && n.questTarget.x !== undefined && n.questTarget.y !== undefined && !n.questTarget._destroyed) {
tx = n.questTarget.x;
ty = n.questTarget.y;
} else if (n.questTarget.x !== undefined && n.questTarget.y !== undefined) {
tx = n.questTarget.x;
ty = n.questTarget.y;
}
if (typeof tx === "number" && typeof ty === "number") {
var tpos = toMiniMap(tx, ty);
var color = 0xffff00;
if (n.questType === 'explore') color = 0x00ffcc;
if (n.questType === 'delivery') color = 0xffcc00;
if (n.questType === 'escort') color = 0x00ff99;
if (n.questType === 'hunt') color = 0xff4444;
var targetDot = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
x: tpos.x,
y: tpos.y,
scaleX: 0.22,
scaleY: 0.22,
tint: color,
alpha: 0.95
});
miniMapContainer.addChild(targetDot);
window._miniMapElements.push(targetDot);
// Add label
var label = new Text2(n.questType.charAt(0).toUpperCase() + n.questType.slice(1), {
size: 18,
fill: color,
align: "center"
});
label.anchor.set(0.5, 0);
label.x = tpos.x;
label.y = tpos.y + 12;
miniMapContainer.addChild(label);
window._miniMapElements.push(label);
}
}
}
// Draw derelict ship
if (window.derelictShip && window.derelictShip.x !== undefined && window.derelictShip.y !== undefined) {
var d = window.derelictShip;
var dpos = toMiniMap(d.x, d.y);
var derelictDot = LK.getAsset('ship', {
anchorX: 0.5,
anchorY: 0.5,
x: dpos.x,
y: dpos.y,
scaleX: 0.22,
scaleY: 0.22,
tint: 0xcccccc,
alpha: 0.8
});
miniMapContainer.addChild(derelictDot);
window._miniMapElements.push(derelictDot);
var label = new Text2("Gemi", {
size: 16,
fill: 0xcccccc,
align: "center"
});
label.anchor.set(0.5, 0);
label.x = dpos.x;
label.y = dpos.y + 10;
miniMapContainer.addChild(label);
window._miniMapElements.push(label);
}
// Draw distress event
if (window.distressEvent && window.distressEvent.x !== undefined && window.distressEvent.y !== undefined) {
var e = window.distressEvent;
var epos = toMiniMap(e.x, e.y);
var distressDot = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
x: epos.x,
y: epos.y,
scaleX: 0.22,
scaleY: 0.22,
tint: 0xff00ff,
alpha: 0.8
});
miniMapContainer.addChild(distressDot);
window._miniMapElements.push(distressDot);
var label = new Text2("İmdat", {
size: 16,
fill: 0xff00ff,
align: "center"
});
label.anchor.set(0.5, 0);
label.x = epos.x;
label.y = epos.y + 10;
miniMapContainer.addChild(label);
window._miniMapElements.push(label);
}
// Draw trade stations
for (var i = 0; i < tradeStations.length; i++) {
var ts = tradeStations[i];
var tpos = toMiniMap(ts.x, ts.y);
var tradeDot = LK.getAsset('npc', {
anchorX: 0.5,
anchorY: 0.5,
x: tpos.x,
y: tpos.y,
scaleX: 0.16,
scaleY: 0.16,
tint: 0x00ffcc,
alpha: 0.7
});
miniMapContainer.addChild(tradeDot);
window._miniMapElements.push(tradeDot);
}
// Draw upgrade stations
for (var i = 0; i < upgradeStations.length; i++) {
var us = upgradeStations[i];
var upos = toMiniMap(us.x, us.y);
var upgDot = LK.getAsset('pirate', {
anchorX: 0.5,
anchorY: 0.5,
x: upos.x,
y: upos.y,
scaleX: 0.16,
scaleY: 0.16,
tint: 0x00ffff,
alpha: 0.7
});
miniMapContainer.addChild(upgDot);
window._miniMapElements.push(upgDot);
}
// Draw black holes
for (var i = 0; i < blackHoles.length; i++) {
var bh = blackHoles[i];
var bhpos = toMiniMap(bh.x, bh.y);
var bhDot = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
x: bhpos.x,
y: bhpos.y,
scaleX: 0.18,
scaleY: 0.18,
tint: 0x222222,
alpha: 0.7
});
miniMapContainer.addChild(bhDot);
window._miniMapElements.push(bhDot);
}
// Draw wormholes
for (var i = 0; i < wormholes.length; i++) {
var wh = wormholes[i];
var whpos = toMiniMap(wh.x, wh.y);
var whDot = LK.getAsset('star', {
anchorX: 0.5,
anchorY: 0.5,
x: whpos.x,
y: whpos.y,
scaleX: 0.18,
scaleY: 0.18,
tint: 0x00ffff,
alpha: 0.7
});
miniMapContainer.addChild(whDot);
window._miniMapElements.push(whDot);
}
// Draw pirate bases
for (var i = 0; i < pirateBases.length; i++) {
var pb = pirateBases[i];
var pbpos = toMiniMap(pb.x, pb.y);
var pbDot = LK.getAsset('pirate', {
anchorX: 0.5,
anchorY: 0.5,
x: pbpos.x,
y: pbpos.y,
scaleX: 0.22,
scaleY: 0.22,
tint: 0xff00ff,
alpha: 0.8
});
miniMapContainer.addChild(pbDot);
window._miniMapElements.push(pbDot);
var label = new Text2("Üs", {
size: 16,
fill: 0xff00ff,
align: "center"
});
label.anchor.set(0.5, 0);
label.x = pbpos.x;
label.y = pbpos.y + 10;
miniMapContainer.addChild(label);
window._miniMapElements.push(label);
}
// Draw asteroids (only those close to ship)
for (var i = 0; i < asteroids.length; i++) {
var a = asteroids[i];
var dist = Math.sqrt(Math.pow(a.x - ship.x, 2) + Math.pow(a.y - ship.y, 2));
if (dist > 3000) continue;
var apos = toMiniMap(a.x, a.y);
var aDot = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: apos.x,
y: apos.y,
scaleX: 0.12,
scaleY: 0.12,
tint: 0x8B4513,
alpha: 0.6
});
miniMapContainer.addChild(aDot);
window._miniMapElements.push(aDot);
}
// Draw label
var title = new Text2("Mini Map", {
size: 32,
fill: 0xffffff,
align: "center"
});
title.anchor.set(0.5, 0);
title.x = mapSize / 2;
title.y = 10;
miniMapContainer.addChild(title);
window._miniMapElements.push(title);
// Draw close hint
var hint = new Text2("Kapatmak için tekrar dokun", {
size: 18,
fill: 0xcccccc,
align: "center"
});
hint.anchor.set(0.5, 1);
hint.x = mapSize / 2;
hint.y = mapSize - 10;
miniMapContainer.addChild(hint);
window._miniMapElements.push(hint);
} else if (window._miniMapContainer && window._miniMapContainer.parent) {
window._miniMapContainer.parent.removeChild(window._miniMapContainer);
window._miniMapElements = [];
window._miniMapContainer = null;
}
}
;
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, then %10 büyüt)
var unifiedFontSize = Math.round(38 * 0.7 * 1.1);
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);
// --- GAME TIME LABEL ---
// Track game start time in ticks
var gameStartTick = LK.ticks;
var gameTimeText = new Text2('Game Time: 0:00', {
size: unifiedFontSize,
fill: 0xcccccc
});
gameTimeText.anchor.set(0, 0);
gameTimeText.x = coinText.x + coinText.width + 40;
gameTimeText.y = coinText.y;
LK.gui.topLeft.addChild(gameTimeText);
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);
healthText._isHealthBar = true; // Mark for tap detection
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);
// No wave, minimap, exp, or coordinate UI in this version
// 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);
}
// No upgrade stations in this version
// No trade stations in this version
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);
}
}
// No black holes or wormholes in this version
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;
}
}
// --- MINI MAP BUTTON HANDLER ---
if (game._miniMapBtn && game._miniMapBtn.parent) {
// Mini map button is about 180x80 px, left of Reset
// x: 2048 - 400 to 2048 - 220, y: 2732 - 100 to 2732
if (x > 2048 - 400 && x < 2048 - 220 && y > 2732 - 100 && y < 2732) {
window._miniMapVisible = !window._miniMapVisible;
// If hiding, remove all mini map elements
if (!window._miniMapVisible && window._miniMapContainer && window._miniMapContainer.parent) {
window._miniMapContainer.parent.removeChild(window._miniMapContainer);
window._miniMapElements = [];
window._miniMapContainer = null;
}
// If showing, force a minimap update by calling the minimap overlay logic
if (window._miniMapVisible) {
// The minimap overlay is drawn in the main game loop, so we just need to trigger a redraw
// by setting _miniMapVisible = true. The next game.update will draw it.
// Optionally, we can force a redraw immediately by calling game.update() if needed.
if (typeof game.update === "function") {
game.update();
}
}
return;
}
}
if (window.repairPanel && window.repairBtn && window.repairBtn.parent) {
// Check tap on repair button
var btn = window.repairBtn;
var bx = btn.x,
by = btn.y;
if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) {
// Try to repair
var costCoins = btn._repairCostCoins,
costMetal = btn._repairCostMetal,
costEnergy = btn._repairCostEnergy;
if (playerCoins >= costCoins && playerMetal >= costMetal && playerEnergy >= costEnergy) {
playerCoins -= costCoins;
playerMetal -= costMetal;
playerEnergy -= costEnergy;
ship.health = ship.maxHealth;
updateUI();
saveProgress();
// Show feedback
btn.setText("Tamir Edildi!");
btn.fill = 0x00ffcc;
// Remove panel after short delay
var expire = LK.ticks + 40;
var origUpdate = game.update;
game.update = function () {
if (LK.ticks > expire) {
if (window.repairPanel && window.repairPanel.parent) window.repairPanel.parent.removeChild(window.repairPanel);
if (window.repairText && window.repairText.parent) window.repairText.parent.removeChild(window.repairText);
if (window.repairBtn && window.repairBtn.parent) window.repairBtn.parent.removeChild(window.repairBtn);
if (window.cancelRepairBtn && window.cancelRepairBtn.parent) window.cancelRepairBtn.parent.removeChild(window.cancelRepairBtn);
window.repairPanel = null;
window.repairText = null;
window.repairBtn = null;
window.cancelRepairBtn = null;
game.update = origUpdate;
}
if (origUpdate) origUpdate.apply(game, arguments);
};
} else {
// Not enough resources
btn.setText("Yetersiz kaynak!");
btn.fill = 0xff4444;
}
return;
}
// Check tap on cancel button
var cbtn = window.cancelRepairBtn;
var cbx = cbtn.x,
cby = cbtn.y;
if (x > cbx - 90 && x < cbx + 90 && y > cby - 40 && y < cby + 40) {
if (window.repairPanel.parent) window.repairPanel.parent.removeChild(window.repairPanel);
if (window.repairText && window.repairText.parent) window.repairText.parent.removeChild(window.repairText);
if (window.repairBtn && window.repairBtn.parent) window.repairBtn.parent.removeChild(window.repairBtn);
if (window.cancelRepairBtn && window.cancelRepairBtn.parent) window.cancelRepairBtn.parent.removeChild(window.cancelRepairBtn);
window.repairPanel = null;
window.repairText = null;
window.repairBtn = null;
window.cancelRepairBtn = null;
return;
}
}
// --- Health bar tap to show repair panel ---
if (healthText && healthText.parent && healthText._isHealthBar && ship.health < ship.maxHealth && ship.health > 0) {
// Get healthText bounds in screen coordinates
// healthText is anchored at (0.5, 0), at top center
// Let's estimate its bounds
var hx = healthText.x,
hy = healthText.y;
var hw = healthText.width || 300;
var hh = healthText.height || 60;
// Accept generous tap area
if (x > hx - hw / 2 && x < hx + hw / 2 && y > hy && y < hy + hh) {
window._showRepairPanel = true;
return;
}
}
// --- SHIP TAP: Show upgrade/can-buy-health panel ---
if (ship && ship.parent) {
// Ship is at (ship.x, ship.y), size is 80x100 (see asset)
var sx = ship.x,
sy = ship.y;
var sw = 80,
sh = 100;
// Accept generous tap area
if (x > sx - sw / 2 && x < sx + sw / 2 && y > sy - sh / 2 && y < sy + sh / 2) {
// Only show if not already shown
if (!window.shipUpgradePanel) {
// Panel background
// --- DYNAMIC PANEL SIZE BASED ON CONTENT ---
var upgBtnFont = unifiedFontSize;
var upgBtnWidth = 340;
var upgBtnHeight = 90;
var colSpacing = 80;
var colXOffset = upgBtnWidth / 2 + colSpacing / 2;
var upgBtnSpacingY = 140;
var numUpgradeRows = 4; // 3 upgrade rows + 1 buy health row
var panelContentHeight = 100 + numUpgradeRows * upgBtnSpacingY + 2 * upgBtnHeight; // title + upgrades + buy health + speed + some margin
var panelContentWidth = upgBtnWidth * 2 + colSpacing + 80; // two columns + spacing + margin
// Add extra for speed upgrade and close button
panelContentHeight += upgBtnSpacingY + 60; // speed upgrade + close btn margin
// Clamp min/max
var panelWidth = Math.max(700, Math.round(panelContentWidth));
var panelHeight = Math.max(340, Math.round(panelContentHeight));
var panel = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: sx,
y: sy - 220,
scaleX: panelWidth / 40,
// asset is 40px wide
scaleY: panelHeight / 40,
// asset is 40px tall
tint: 0x224488
});
// Title
var titleFont = Math.round(62 * 1.1);
var title = new Text2("Yükseltmeler & Can Satın Al", {
size: titleFont,
fill: 0xffffff,
align: "center"
});
title.anchor.set(0.5, 0.5);
title.x = sx;
title.y = sy - 220 - panelHeight / 2 + 100;
// Upgrade buttons, dikeyde aralıklı ve panelin içine sığacak şekilde
var upgBtnY = title.y + 110;
var upgBtnSpacingY = 140;
// Paneldeki yazı ve butonların font boyutunu, Wave font boyutu ile aynı yap
var upgBtnFont = unifiedFontSize;
var upgBtnWidth = 340;
var upgBtnHeight = 90;
var colSpacing = 80;
var colXOffset = upgBtnWidth / 2 + colSpacing / 2;
// Normal upgrades
var upg1 = new Text2("Max Can +20\n(100 coin, 10 metal)", {
size: upgBtnFont,
fill: 0x00ff99,
align: "center"
});
upg1.anchor.set(0.5, 0.5);
upg1.x = sx - colXOffset;
upg1.y = upgBtnY;
upg1._isShipUpgradeBtn = true;
upg1._upgradeType = "maxHealth";
upg1._upgradeCost = {
coins: 100,
metal: 10,
energy: 0
};
var upg1x2 = new Text2("Max Can +20\n(200 coin, 20 metal)", {
size: upgBtnFont,
fill: 0x00cc99,
align: "center"
});
upg1x2.anchor.set(0.5, 0.5);
upg1x2.x = sx + colXOffset;
upg1x2.y = upgBtnY;
upg1x2._isShipUpgradeBtn = true;
upg1x2._upgradeType = "maxHealth";
upg1x2._upgradeCost = {
coins: 200,
metal: 20,
energy: 0
};
upg1x2._isDoubleCost = true;
var upg2 = new Text2("Max Kalkan +10\n(120 coin, 12 metal)", {
size: upgBtnFont,
fill: 0x00ccff,
align: "center"
});
upg2.anchor.set(0.5, 0.5);
upg2.x = sx - colXOffset;
upg2.y = upgBtnY + upgBtnSpacingY;
upg2._isShipUpgradeBtn = true;
upg2._upgradeType = "maxShield";
upg2._upgradeCost = {
coins: 120,
metal: 12,
energy: 0
};
var upg2x2 = new Text2("Max Kalkan +10\n(240 coin, 24 metal)", {
size: upgBtnFont,
fill: 0x00aaff,
align: "center"
});
upg2x2.anchor.set(0.5, 0.5);
upg2x2.x = sx + colXOffset;
upg2x2.y = upgBtnY + upgBtnSpacingY;
upg2x2._isShipUpgradeBtn = true;
upg2x2._upgradeType = "maxShield";
upg2x2._upgradeCost = {
coins: 240,
metal: 24,
energy: 0
};
upg2x2._isDoubleCost = true;
var upg3 = new Text2("Hasar +5\n(150 coin, 15 enerji)", {
size: upgBtnFont,
fill: 0xffcc00,
align: "center"
});
upg3.anchor.set(0.5, 0.5);
upg3.x = sx - colXOffset;
upg3.y = upgBtnY + upgBtnSpacingY * 2;
upg3._isShipUpgradeBtn = true;
upg3._upgradeType = "damage";
upg3._upgradeCost = {
coins: 150,
metal: 0,
energy: 15
};
var upg3x2 = new Text2("Hasar +5\n(300 coin, 30 enerji)", {
size: upgBtnFont,
fill: 0xff9900,
align: "center"
});
upg3x2.anchor.set(0.5, 0.5);
upg3x2.x = sx + colXOffset;
upg3x2.y = upgBtnY + upgBtnSpacingY * 2;
upg3x2._isShipUpgradeBtn = true;
upg3x2._upgradeType = "damage";
upg3x2._upgradeCost = {
coins: 300,
metal: 0,
energy: 30
};
upg3x2._isDoubleCost = true;
// Buy health button (if not full)
var canBuyHealth = ship.health < ship.maxHealth;
var buyHealthBtnFont = unifiedFontSize;
// Proportional cost scaling for buy health button
var healthToRestore = ship.maxHealth - ship.health;
var baseFullRepairHealth = 60;
var baseCoinCost = 90;
var baseMetalCost = 6;
var baseEnergyCost = 6;
var buyHealthCostCoins = Math.max(30, Math.round(baseCoinCost * (healthToRestore / baseFullRepairHealth)));
var buyHealthCostMetal = Math.max(2, Math.round(baseMetalCost * (healthToRestore / baseFullRepairHealth)));
var buyHealthCostEnergy = Math.max(2, Math.round(baseEnergyCost * (healthToRestore / baseFullRepairHealth)));
var buyHealthBtn = new Text2("Canı Doldur (" + buyHealthCostCoins + " coin, " + buyHealthCostMetal + " metal, " + buyHealthCostEnergy + " enerji)", {
size: buyHealthBtnFont,
fill: canBuyHealth ? 0x00ffcc : 0x888888,
align: "center"
});
buyHealthBtn.anchor.set(0.5, 0.5);
buyHealthBtn.x = sx;
buyHealthBtn.y = upgBtnY + upgBtnSpacingY * 3 + 30;
buyHealthBtn._isShipBuyHealthBtn = true;
buyHealthBtn._repairCostCoins = buyHealthCostCoins;
buyHealthBtn._repairCostMetal = buyHealthCostMetal;
buyHealthBtn._repairCostEnergy = buyHealthCostEnergy;
// Speed upgrade button (bottom of panel)
var speedUpgLevel = window.shipSpeedUpgradeLevel || 0;
var speedUpgFont = unifiedFontSize;
var speedUpgCost = 120 + speedUpgLevel * 60;
var speedUpgBtn = new Text2("Hız +" + Math.round((speedUpgLevel + 1) * 10) + "%\n(" + speedUpgCost + " coin)", {
size: speedUpgFont,
fill: 0x00ffff,
align: "center"
});
speedUpgBtn.anchor.set(0.5, 0.5);
speedUpgBtn.x = sx;
speedUpgBtn.y = buyHealthBtn.y + upgBtnSpacingY;
speedUpgBtn._isShipSpeedUpgradeBtn = true;
speedUpgBtn._speedUpgradeLevel = speedUpgLevel;
speedUpgBtn._speedUpgradeCost = speedUpgCost;
// Close button
var closeBtnFont = unifiedFontSize;
var closeBtn = new Text2("Kapat", {
size: closeBtnFont,
fill: 0xff4444,
align: "center"
});
closeBtn.anchor.set(0.5, 0.5);
// Move close button above the panel title, with extra margin
closeBtn.x = sx;
closeBtn.y = title.y - 90;
closeBtn._isShipUpgradeCloseBtn = true;
// Add to game
game.addChild(panel);
game.addChild(title);
game.addChild(upg1);
game.addChild(upg1x2);
game.addChild(upg2);
game.addChild(upg2x2);
game.addChild(upg3);
game.addChild(upg3x2);
game.addChild(buyHealthBtn);
game.addChild(speedUpgBtn);
game.addChild(closeBtn);
// Store refs for tap logic/cleanup
window.shipUpgradePanel = panel;
window.shipUpgradeTitle = title;
window.shipUpgradeBtn1 = upg1;
window.shipUpgradeBtn1x2 = upg1x2;
window.shipUpgradeBtn2 = upg2;
window.shipUpgradeBtn2x2 = upg2x2;
window.shipUpgradeBtn3 = upg3;
window.shipUpgradeBtn3x2 = upg3x2;
window.shipBuyHealthBtn = buyHealthBtn;
window.shipSpeedUpgradeBtn = speedUpgBtn;
window.shipUpgradeCloseBtn = closeBtn;
}
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) {
ship.boostSpeed = 10;
ship.boostCooldown = 300; // 5 seconds cooldown
if (LK.getSound('boost')) {
LK.getSound('boost').play();
}
} else {
// --- SHIP UPGRADE PANEL BUTTONS ---
if (window.shipUpgradePanel) {
// Upgrade buttons
var btns = [window.shipUpgradeBtn1, window.shipUpgradeBtn1x2, window.shipUpgradeBtn2, window.shipUpgradeBtn2x2, window.shipUpgradeBtn3, window.shipUpgradeBtn3x2];
for (var i = 0; i < btns.length; i++) {
var btn = btns[i];
if (!btn) continue;
var bx = btn.x,
by = btn.y;
if (x > bx - 120 && x < bx + 120 && y > by - 50 && y < by + 50) {
// Try to buy upgrade
var upg = btn._upgradeType;
var cost = btn._upgradeCost;
var isDouble = !!btn._isDoubleCost;
if (upg === "maxHealth" && playerCoins >= cost.coins && playerMetal >= cost.metal) {
ship.maxHealth += 20;
ship.health = ship.maxHealth;
playerCoins -= cost.coins;
playerMetal -= cost.metal;
LK.effects.flashObject(ship, isDouble ? 0x00cc99 : 0x00ff99, 400);
btn.setText("Alındı!");
btn.fill = 0x00ffcc;
updateUI();
saveProgress();
} else if (upg === "maxShield" && playerCoins >= cost.coins && playerMetal >= cost.metal) {
ship.maxShield += 10;
ship.shield = ship.maxShield;
playerCoins -= cost.coins;
playerMetal -= cost.metal;
LK.effects.flashObject(ship, isDouble ? 0x00aaff : 0x00ccff, 400);
btn.setText("Alındı!");
btn.fill = 0x00ffcc;
updateUI();
saveProgress();
} else if (upg === "damage" && playerCoins >= cost.coins && playerEnergy >= cost.energy) {
ship.damage += 5;
playerCoins -= cost.coins;
playerEnergy -= cost.energy;
LK.effects.flashObject(ship, isDouble ? 0xff9900 : 0xffcc00, 400);
btn.setText("Alındı!");
btn.fill = 0x00ffcc;
updateUI();
saveProgress();
} else {
btn.setText("Yetersiz kaynak!");
btn.fill = 0xff4444;
}
return;
}
}
// Buy health button
var bhb = window.shipBuyHealthBtn;
if (bhb) {
var bx = bhb.x,
by = bhb.y;
if (x > bx - 180 && x < bx + 180 && y > by - 50 && y < by + 50) {
if (ship.health < ship.maxHealth) {
var costCoins = bhb._repairCostCoins,
costMetal = bhb._repairCostMetal,
costEnergy = bhb._repairCostEnergy;
if (playerCoins >= costCoins && playerMetal >= costMetal && playerEnergy >= costEnergy) {
playerCoins -= costCoins;
playerMetal -= costMetal;
playerEnergy -= costEnergy;
ship.health = ship.maxHealth;
updateUI();
saveProgress();
bhb.setText("Can Dolduruldu!");
bhb.fill = 0x00ffcc;
} else {
bhb.setText("Yetersiz kaynak!");
bhb.fill = 0xff4444;
}
} else {
bhb.setText("Can zaten tam!");
bhb.fill = 0x888888;
}
return;
}
}
// Speed upgrade button
var sub = window.shipSpeedUpgradeBtn;
if (sub) {
var bx = sub.x,
by = sub.y;
if (x > bx - 180 && x < bx + 180 && y > by - 50 && y < by + 50) {
var level = window.shipSpeedUpgradeLevel || 0;
var cost = 120 + level * 60;
if (playerCoins >= cost) {
playerCoins -= cost;
level++;
window.shipSpeedUpgradeLevel = level;
// Each level increases speed by 10% (multiplicative)
ship.speed = Math.round(ship.speed * Math.pow(1.1, 1) * 100) / 100;
sub.setText("Alındı! +" + level * 10 + "%");
sub.fill = 0x00ffcc;
LK.effects.flashObject(ship, 0x00ffff, 400);
updateUI();
saveProgress();
} else {
sub.setText("Yetersiz coin!");
sub.fill = 0xff4444;
}
return;
}
}
// Close button
var cb = window.shipUpgradeCloseBtn;
if (cb) {
var bx = cb.x,
by = cb.y;
if (x > bx - 120 && x < bx + 120 && y > by - 50 && y < by + 50) {
// Remove all panel elements
if (window.shipUpgradePanel && window.shipUpgradePanel.parent) window.shipUpgradePanel.parent.removeChild(window.shipUpgradePanel);
if (window.shipUpgradeTitle && window.shipUpgradeTitle.parent) window.shipUpgradeTitle.parent.removeChild(window.shipUpgradeTitle);
if (window.shipUpgradeBtn1 && window.shipUpgradeBtn1.parent) window.shipUpgradeBtn1.parent.removeChild(window.shipUpgradeBtn1);
if (window.shipUpgradeBtn1x2 && window.shipUpgradeBtn1x2.parent) window.shipUpgradeBtn1x2.parent.removeChild(window.shipUpgradeBtn1x2);
if (window.shipUpgradeBtn2 && window.shipUpgradeBtn2.parent) window.shipUpgradeBtn2.parent.removeChild(window.shipUpgradeBtn2);
if (window.shipUpgradeBtn2x2 && window.shipUpgradeBtn2x2.parent) window.shipUpgradeBtn2x2.parent.removeChild(window.shipUpgradeBtn2x2);
if (window.shipUpgradeBtn3 && window.shipUpgradeBtn3.parent) window.shipUpgradeBtn3.parent.removeChild(window.shipUpgradeBtn3);
if (window.shipUpgradeBtn3x2 && window.shipUpgradeBtn3x2.parent) window.shipUpgradeBtn3x2.parent.removeChild(window.shipUpgradeBtn3x2);
if (window.shipBuyHealthBtn && window.shipBuyHealthBtn.parent) window.shipBuyHealthBtn.parent.removeChild(window.shipBuyHealthBtn);
if (window.shipSpeedUpgradeBtn && window.shipSpeedUpgradeBtn.parent) window.shipSpeedUpgradeBtn.parent.removeChild(window.shipSpeedUpgradeBtn);
if (window.shipUpgradeCloseBtn && window.shipUpgradeCloseBtn.parent) window.shipUpgradeCloseBtn.parent.removeChild(window.shipUpgradeCloseBtn);
// Hide all upgrade panel texts
window.shipUpgradePanel = null;
window.shipUpgradeTitle = null;
window.shipUpgradeBtn1 = null;
window.shipUpgradeBtn1x2 = null;
window.shipUpgradeBtn2 = null;
window.shipUpgradeBtn2x2 = null;
window.shipUpgradeBtn3 = null;
window.shipUpgradeBtn3x2 = null;
window.shipBuyHealthBtn = null;
window.shipSpeedUpgradeBtn = null;
window.shipUpgradeCloseBtn = null;
return;
}
}
}
// --- 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);
var killedByPlayer = !bullet._npcBullet;
var killedByNPC = !!bullet._npcBullet;
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);
}
// Remove KILL label after 2 seconds if present
if (pirates[j]._killLabel) {
// If not already expiring, set expire tick
if (!pirates[j]._killLabel._expireTick) {
pirates[j]._killLabel._expireTick = LK.ticks + 120;
}
}
// Remove KILL label if expired
if (pirates[j]._killLabel && pirates[j]._killLabel._expireTick && LK.ticks > pirates[j]._killLabel._expireTick) {
if (pirates[j]._killLabel.parent) pirates[j]._killLabel.parent.removeChild(pirates[j]._killLabel);
pirates[j]._killLabel = null;
}
if (killedByPlayer) {
// Oyuncu öldürdü: +rep ve exp
playerGoodRep += 1;
var pirateExp = 3 + Math.floor(Math.random() * 3);
playerEXP += pirateExp;
// Rep/exp etiketi gösterme, tamamen kaldırıldı
} else if (killedByNPC) {
// NPC öldürdü: yoluna devam etsin, rep/exp yok
// Kısa bir etiket göster (isteğe bağlı)
var npcLabel = new Text2("NPC KILL", {
size: 28,
fill: 0xccccff,
align: "center"
});
npcLabel.anchor.set(0.5, 0.5);
npcLabel.x = pirates[j].x;
npcLabel.y = pirates[j].y - 80;
game.addChild(npcLabel);
(function (lbl) {
var expire = LK.ticks + 40;
var origUpdate = game.update;
game.update = function () {
if (LK.ticks > expire && lbl.parent) {
lbl.parent.removeChild(lbl);
game.update = origUpdate;
}
if (origUpdate) origUpdate.apply(game, arguments);
};
})(npcLabel);
}
// 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();
// --- Pirate AI: Attack nearest NPC if close ---
var nearestNPC = null;
var minDistNPC = Infinity;
for (var n = 0; n < npcs.length; n++) {
var npc = npcs[n];
var distToNPC = Math.sqrt(Math.pow(npc.x - pirate.x, 2) + Math.pow(npc.y - pirate.y, 2));
if (distToNPC < minDistNPC) {
minDistNPC = distToNPC;
nearestNPC = npc;
}
}
// 50% chance to attack NPC if close, otherwise wander
if (nearestNPC && minDistNPC < 350 && Math.random() < 0.5) {
// Move toward NPC
var angle = Math.atan2(nearestNPC.y - pirate.y, nearestNPC.x - pirate.x);
pirate.x += Math.cos(angle) * pirate.speed;
pirate.y += Math.sin(angle) * pirate.speed;
pirate.rotation = angle + Math.PI / 2;
// Shoot at NPC
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);
bullet.rotation = angle + Math.PI / 2;
bullet._pirateBullet = true;
enemyBullets.push(bullet);
game.addChild(bullet);
pirate.lastFire = LK.ticks;
}
} else {
// Wander randomly
pirate.x += Math.cos(pirate.moveAngle) * pirate.speed * 0.5;
pirate.y += Math.sin(pirate.moveAngle) * pirate.speed * 0.5;
}
// Remove pirates that are too far away
var dist = Math.sqrt(Math.pow(ship.x - pirate.x, 2) + Math.pow(ship.y - pirate.y, 2));
if (dist > 2000) {
pirate.destroy();
pirates.splice(i, 1);
i--;
}
}
// Update NPCs
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;
}
// Remove any floating text if player is not close
if (npc._npcText && npc._npcText.parent) {
npc._npcText.parent.removeChild(npc._npcText);
npc._npcText = null;
}
// --- NPC AI: Attack pirates sometimes ---
// Only if there are pirates and not already targeting one
if (!npc._aiTargetPirate || npc._aiTargetPirate._destroyed) {
// 30% chance to pick a new pirate target
if (pirates.length > 0 && Math.random() < 0.3) {
// Find nearest pirate
var minDist = Infinity;
var targetPirate = null;
for (var j = 0; j < pirates.length; j++) {
var p = pirates[j];
if (p._destroyed) continue;
var d = Math.sqrt(Math.pow(p.x - npc.x, 2) + Math.pow(p.y - npc.y, 2));
if (d < minDist) {
minDist = d;
targetPirate = p;
}
}
if (targetPirate && minDist < 800) {
npc._aiTargetPirate = targetPirate;
npc._aiAttackTimer = 0;
}
}
}
// Attack target pirate if set
if (npc._aiTargetPirate && !npc._aiTargetPirate._destroyed) {
var tp = npc._aiTargetPirate;
var dx = tp.x - npc.x;
var dy = tp.y - npc.y;
var d = Math.sqrt(dx * dx + dy * dy);
// Approach
if (d > 120) {
npc.x += dx / d * npc.moveSpeed * 1.2;
npc.y += dy / d * npc.moveSpeed * 1.2;
}
// Shoot (every 30 ticks)
npc._aiAttackTimer = (npc._aiAttackTimer || 0) + 1;
if (d < 300 && npc._aiAttackTimer > 30) {
var bullet = new Bullet();
bullet.x = npc.x;
bullet.y = npc.y;
var angle = Math.atan2(tp.y - npc.y, tp.x - npc.x);
bullet.directionX = Math.cos(angle);
bullet.directionY = Math.sin(angle);
bullet.rotation = angle + Math.PI / 2;
bullet._npcBullet = true;
bullets.push(bullet);
game.addChild(bullet);
npc._aiAttackTimer = 0;
}
if (tp.health <= 0 || tp._destroyed) {
npc._aiTargetPirate = null;
}
} else {
npc._aiTargetPirate = 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);
}
}
// 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);
}
}
// No pirate bases, black holes, wormholes, or special buildings
// Spawn entities (star spawn frequency increased 3x)
if (LK.ticks % 33 === 0) {
if (Math.random() < 0.5) {
spawnStar();
}
// Spawn pirates and NPCs at intervals
if (pirates.length < 6 && Math.random() < 0.3) {
spawnPirate();
}
if (npcs.length < 4 && Math.random() < 0.2) {
spawnNPC();
}
}
// Update score
LK.setScore(playerCoins + questsCompleted * 100 + enemiesKilled * 10 + Math.floor(totalDistance / 100));
if (ship._healthBar && ship._healthBar.update) ship._healthBar.update();
updateUI();
// --- AUTO-REPAIR PANEL WHEN HEALTH IS LOW OR HEALTH BAR TAPPED ---
// Show repair panel if health < 100% and not dead, and not already shown
if (!window.repairPanel && ship.health < ship.maxHealth && ship.health > 0 && window._showRepairPanel) {
// Calculate how much health will be restored
var healthToRestore = ship.maxHealth - ship.health;
// Proportional cost scaling
// Base costs for full repair: 90 coins, 6 metal, 6 energy (for 60 health missing)
// Scale linearly with health to restore, but clamp minimums
var baseFullRepairHealth = 60;
var baseCoinCost = 90;
var baseMetalCost = 6;
var baseEnergyCost = 6;
var repairCostCoins = Math.max(30, Math.round(baseCoinCost * (healthToRestore / baseFullRepairHealth)));
var repairCostMetal = Math.max(2, Math.round(baseMetalCost * (healthToRestore / baseFullRepairHealth)));
var repairCostEnergy = Math.max(2, Math.round(baseEnergyCost * (healthToRestore / baseFullRepairHealth)));
// Panel background
// --- DYNAMIC REPAIR PANEL SIZE BASED ON TEXT ---
var repairTextStr = "Gemi hasarlı! Tamir: " + repairCostCoins + " coin, " + repairCostMetal + " metal, " + repairCostEnergy + " enerji";
var repairPanelFontSize = 38;
var repairPanelWidth = Math.max(700, repairTextStr.length * repairPanelFontSize * 0.32);
var repairPanelHeight = 180 + repairPanelFontSize * 1.5; // text + buttons
var panel = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: ship.x,
y: ship.y - 220,
scaleX: repairPanelWidth / 40,
scaleY: repairPanelHeight / 40,
tint: 0x224444
});
// Repair text
var repairText = new Text2("Gemi hasarlı! Tamir: " + repairCostCoins + " coin, " + repairCostMetal + " metal, " + repairCostEnergy + " enerji", {
size: 38,
fill: 0xffffff,
align: "center"
});
repairText.anchor.set(0.5, 0.5);
repairText.x = ship.x;
repairText.y = ship.y - 240;
// Repair button
var repairBtn = new Text2("Tamir Et", {
size: 44,
fill: 0x00ff99,
align: "center"
});
repairBtn.anchor.set(0.5, 0.5);
repairBtn.x = ship.x - 100;
repairBtn.y = ship.y - 160;
// Cancel button
var cancelBtn = new Text2("Kapat", {
size: 44,
fill: 0xff4444,
align: "center"
});
cancelBtn.anchor.set(0.5, 0.5);
cancelBtn.x = ship.x + 100;
cancelBtn.y = ship.y - 160;
// Add to game
game.addChild(panel);
game.addChild(repairText);
game.addChild(repairBtn);
game.addChild(cancelBtn);
// Store references for tap logic and cleanup
window.repairPanel = panel;
window.repairText = repairText;
window.repairBtn = repairBtn;
window.cancelRepairBtn = cancelBtn;
repairBtn._isRepairBtn = true;
cancelBtn._isCancelRepairBtn = true;
repairBtn._repairCostCoins = repairCostCoins;
repairBtn._repairCostMetal = repairCostMetal;
repairBtn._repairCostEnergy = repairCostEnergy;
window._showRepairPanel = false; // Reset flag
} else if (window.repairPanel && ship.health >= ship.maxHealth * 0.7) {
// Remove repair panel if health is restored
if (window.repairPanel.parent) window.repairPanel.parent.removeChild(window.repairPanel);
if (window.repairText && window.repairText.parent) window.repairText.parent.removeChild(window.repairText);
if (window.repairBtn && window.repairBtn.parent) window.repairBtn.parent.removeChild(window.repairBtn);
if (window.cancelRepairBtn && window.cancelRepairBtn.parent) window.cancelRepairBtn.parent.removeChild(window.cancelRepairBtn);
window.repairPanel = null;
window.repairText = null;
window.repairBtn = null;
window.cancelRepairBtn = null;
window._showRepairPanel = false;
}
// If health < 50% and not dead, auto-show repair panel (legacy behavior)
if (!window.repairPanel && ship.health < ship.maxHealth * 0.5 && ship.health > 0) {
window._showRepairPanel = true;
}
// --- GAME TIME UPDATE ---
// Calculate elapsed time in seconds
var elapsedTicks = LK.ticks - gameStartTick;
var elapsedSeconds = Math.floor(elapsedTicks / 60);
var minutes = Math.floor(elapsedSeconds / 60);
var seconds = elapsedSeconds % 60;
if (typeof gameTimeText !== "undefined") {
// Format as mm:ss
var timeStr = "Game Time: " + minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
gameTimeText.setText(timeStr);
// Always keep gameTimeText to the right of coinText
gameTimeText.x = coinText.x + coinText.width + 40;
gameTimeText.y = coinText.y;
}
// --- Synchronize LK.ticks with real game time ---
// This ensures all time-based systems use real elapsed time, not just frame count
LK.ticks = gameStartTick + Math.floor((Date.now() - (window._gameStartRealTime || (window._gameStartRealTime = Date.now()))) / (1000 / 60));
// 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;
}
// --- QUEST TARGET ARROW INDICATOR ---
// Only one arrow at a time, create if needed
if (!window.questArrow) {
// Use a yellow triangle as arrow
var arrow = LK.getAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 1.2,
tint: 0xffff00,
alpha: 0.85
});
arrow.visible = false;
window.questArrow = arrow;
game.addChild(arrow);
}
var showArrow = false;
var arrowX = 0,
arrowY = 0,
arrowRot = 0;
var questTarget = null;
var minDist = Infinity;
// Find the nearest active coordinate-based quest target
for (var i = 0; i < npcs.length; i++) {
var npc = npcs[i];
if (!npc.questActive || !npc.questTarget) continue;
// Only for coordinate-based quests
if (npc.questType === 'explore' || npc.questType === 'delivery' || npc.questType === 'escort' || npc.questType === 'hunt') {
// For hunt, questTarget can be a pirate, otherwise it's {x, y}
var tx, ty;
if (npc.questType === 'hunt' && npc.questTarget && npc.questTarget.x !== undefined && npc.questTarget.y !== undefined && !npc.questTarget._destroyed) {
tx = npc.questTarget.x;
ty = npc.questTarget.y;
} else if (npc.questTarget.x !== undefined && npc.questTarget.y !== undefined) {
tx = npc.questTarget.x;
ty = npc.questTarget.y;
}
if (typeof tx === "number" && typeof ty === "number") {
var dist = Math.sqrt(Math.pow(tx - ship.x, 2) + Math.pow(ty - ship.y, 2));
if (dist > 120 && dist < minDist) {
// Only show if not already at target
minDist = dist;
questTarget = {
x: tx,
y: ty
};
}
}
}
}
// --- Derelict ship arrow logic ---
if (!questTarget && window.derelictShip && window.derelictShip.x !== undefined && window.derelictShip.y !== undefined) {
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 && dist < 3000) {
questTarget = {
x: d.x,
y: d.y
};
}
}
if (questTarget) {
// Project questTarget to screen edge
var dx = questTarget.x - ship.x;
var dy = questTarget.y - ship.y;
var angle = Math.atan2(dy, dx);
// Screen center in game coordinates
var screenW = 2048,
screenH = 2732;
var margin = 90; // keep arrow inside screen
var cx = screenW / 2,
cy = screenH / 2;
// Find intersection with screen edge
var ex = cx + Math.cos(angle) * (Math.min(cx, cy) - margin);
var ey = cy + Math.sin(angle) * (Math.min(cx, cy) - margin);
// Clamp to screen bounds
ex = Math.max(margin, Math.min(screenW - margin, ex));
ey = Math.max(margin, Math.min(screenH - margin, ey));
// Don't show if target is on screen (within 40% of screen from center)
if (Math.abs(dx) > screenW * 0.2 || Math.abs(dy) > screenH * 0.2) {
showArrow = true;
arrowX = ex;
arrowY = ey;
arrowRot = angle + Math.PI / 2;
}
}
if (window.questArrow) {
window.questArrow.visible = showArrow;
if (showArrow) {
window.questArrow.x = arrowX;
window.questArrow.y = arrowY;
window.questArrow.rotation = arrowRot;
window.questArrow.alpha = 0.85 + Math.sin(LK.ticks * 0.1) * 0.15;
window.questArrow.scaleX = 2.5 + Math.sin(LK.ticks * 0.07) * 0.2;
window.questArrow.scaleY = 1.2 + Math.cos(LK.ticks * 0.09) * 0.1;
window.questArrow.zIndex = 9999;
}
}
// --- Remaining Distance Label for Quest/Event Target ---
// Only one label at a time, create if needed
if (!window.questDistanceLabel) {
var questDistanceLabel = new Text2('', {
size: Math.round(unifiedFontSize * 0.9),
fill: 0xffffff,
align: "center"
});
questDistanceLabel.anchor.set(0.5, 0.5);
questDistanceLabel.visible = false;
window.questDistanceLabel = questDistanceLabel;
game.addChild(questDistanceLabel);
}
var showDistanceLabel = false;
var labelX = 0,
labelY = 0,
labelText = '';
if (questTarget) {
// Calculate distance
var distToTarget = Math.sqrt(Math.pow(questTarget.x - ship.x, 2) + Math.pow(questTarget.y - ship.y, 2));
// Only show if not already at target and not on screen
if (showArrow && distToTarget > 120) {
showDistanceLabel = true;
// Place label near the arrow, but offset further outwards
var labelOffset = 70;
labelX = arrowX + Math.cos(arrowRot - Math.PI / 2) * labelOffset;
labelY = arrowY + Math.sin(arrowRot - Math.PI / 2) * labelOffset;
// Show in km if >1000, else in px
if (distToTarget >= 1000) {
labelText = Math.round(distToTarget / 10) / 100 + "k px";
} else {
labelText = Math.round(distToTarget) + " px";
}
// If quest is from an NPC, show a short label
for (var i = 0; i < npcs.length; i++) {
var npc = npcs[i];
if (npc.questActive && npc.questTarget && (npc.questType === 'explore' || npc.questType === 'delivery' || npc.questType === 'escort') && npc.questTarget.x === questTarget.x && npc.questTarget.y === questTarget.y) {
if (npc.questType === 'explore') labelText = "Keşif: " + labelText;else if (npc.questType === 'delivery') labelText = "Teslimat: " + labelText;else if (npc.questType === 'escort') labelText = "Eşlik: " + labelText;
break;
}
if (npc.questActive && npc.questType === 'hunt' && npc.questTarget && npc.questTarget.x === questTarget.x && npc.questTarget.y === questTarget.y) {
labelText = "Av: " + labelText;
break;
}
}
}
}
// Derelict ship distance
if (!showDistanceLabel && window.derelictShip && window.derelictShip.x !== undefined && window.derelictShip.y !== undefined) {
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 && dist < 3000 && window.questArrow && window.questArrow.visible) {
showDistanceLabel = true;
var labelOffset = 70;
labelX = window.questArrow.x + Math.cos(window.questArrow.rotation - Math.PI / 2) * labelOffset;
labelY = window.questArrow.y + Math.sin(window.questArrow.rotation - Math.PI / 2) * labelOffset;
labelText = "Gemi: " + (dist >= 1000 ? Math.round(dist / 10) / 100 + "k px" : Math.round(dist) + " px");
}
}
// Distress event distance
if (!showDistanceLabel && window.distressEvent && window.distressEvent.x !== undefined && window.distressEvent.y !== undefined) {
var e = window.distressEvent;
var dist = Math.sqrt(Math.pow(e.x - ship.x, 2) + Math.pow(e.y - ship.y, 2));
if (dist > 120 && dist < 3000 && window.questArrow && window.questArrow.visible) {
showDistanceLabel = true;
var labelOffset = 70;
labelX = window.questArrow.x + Math.cos(window.questArrow.rotation - Math.PI / 2) * labelOffset;
labelY = window.questArrow.y + Math.sin(window.questArrow.rotation - Math.PI / 2) * labelOffset;
labelText = "İmdat: " + (dist >= 1000 ? Math.round(dist / 10) / 100 + "k px" : Math.round(dist) + " px");
}
}
if (window.questDistanceLabel) {
window.questDistanceLabel.visible = showDistanceLabel;
if (showDistanceLabel) {
window.questDistanceLabel.x = labelX;
window.questDistanceLabel.y = labelY;
window.questDistanceLabel.setText(labelText);
window.questDistanceLabel.alpha = 0.9 + Math.sin(LK.ticks * 0.1) * 0.1;
window.questDistanceLabel.size = Math.round(unifiedFontSize * 0.9);
window.questDistanceLabel.zIndex = 9999;
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -772,13 +772,10 @@
var explosions = [];
var blackHoles = [];
var wormholes = [];
var tradeStations = [];
-var pirateBases = []; // NEW: array for pirate bases
-var tradeText = new Text2('', {
- size: 40,
- fill: 0x00ff99
-});
+var pirateBases = [];
+var tradeText = null; // No trade text needed
// 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
@@ -1299,73 +1296,9 @@
});
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;
-// --- MINI MAP BUTTON (bottom right, left of Reset) ---
-var miniMapBtn = new Text2('Mini Map', {
- size: 44,
- fill: 0x00ccff,
- font: "'Heath', Impact, 'Arial Black', Tahoma",
- align: "center"
-});
-miniMapBtn.anchor.set(1, 1);
-miniMapBtn.x = -220; // 180px left of Reset
-miniMapBtn.y = -40;
-LK.gui.bottomRight.addChild(miniMapBtn);
-miniMapBtn._isMiniMapBtn = true;
-game._miniMapBtn = miniMapBtn;
-// --- MINI MAP OVERLAY (hidden by default) ---
-window._miniMapVisible = false;
-window._miniMapElements = [];
-window._miniMapContainer = null;
-// 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);
+// No wave, minimap, exp, or coordinate UI in this version
// Create joystick
joystickBase = game.addChild(LK.getAsset('joystickBase', {
anchorX: 0.5,
anchorY: 0.5,
@@ -1578,40 +1511,10 @@
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);
-}
+// No upgrade stations in this version
+// No trade stations in this version
function createExplosion(x, y) {
for (var i = 0; i < 8; i++) {
var particle = LK.getAsset('explosion', {
anchorX: 0.5,
@@ -1625,58 +1528,9 @@
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);
-}
+// No black holes or wormholes in this version
function createBoostParticle() {
var particle = LK.getAsset('boostParticle', {
anchorX: 0.5,
anchorY: 0.5,
@@ -2702,68 +2556,46 @@
// Update pirates
for (var i = 0; i < pirates.length; i++) {
var pirate = pirates[i];
if (pirate._healthBar && pirate._healthBar.update) pirate._healthBar.update();
- // Rep/exp label logic removed: no rep/exp label is created or cleaned up
- // --- Show "KILL" label above quest target pirate for hunt quests ---
- // (KILL etiketi tamamen kaldırıldı)
- // 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;
+ // --- Pirate AI: Attack nearest NPC if close ---
+ var nearestNPC = null;
+ var minDistNPC = Infinity;
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;
- }
+ var distToNPC = Math.sqrt(Math.pow(npc.x - pirate.x, 2) + Math.pow(npc.y - pirate.y, 2));
+ if (distToNPC < minDistNPC) {
+ minDistNPC = distToNPC;
+ nearestNPC = npc;
}
}
- // 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);
+ // 50% chance to attack NPC if close, otherwise wander
+ if (nearestNPC && minDistNPC < 350 && Math.random() < 0.5) {
+ // Move toward NPC
+ var angle = Math.atan2(nearestNPC.y - pirate.y, nearestNPC.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
+ // Shoot at NPC
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);
+ bullet.rotation = angle + Math.PI / 2;
+ bullet._pirateBullet = true;
enemyBullets.push(bullet);
game.addChild(bullet);
pirate.lastFire = LK.ticks;
}
+ } else {
+ // Wander randomly
+ pirate.x += Math.cos(pirate.moveAngle) * pirate.speed * 0.5;
+ pirate.y += Math.sin(pirate.moveAngle) * pirate.speed * 0.5;
}
+ // Remove pirates that are too far away
+ var dist = Math.sqrt(Math.pow(ship.x - pirate.x, 2) + Math.pow(ship.y - pirate.y, 2));
if (dist > 2000) {
pirate.destroy();
pirates.splice(i, 1);
i--;
@@ -2787,11 +2619,11 @@
}
// --- NPC AI: Attack pirates sometimes ---
// Only if there are pirates and not already targeting one
if (!npc._aiTargetPirate || npc._aiTargetPirate._destroyed) {
- // %20 ihtimalle yeni hedef seçsin
- if (pirates.length > 0 && Math.random() < 0.20) {
- // En yakın korsanı bul
+ // 30% chance to pick a new pirate target
+ if (pirates.length > 0 && Math.random() < 0.3) {
+ // Find nearest pirate
var minDist = Infinity;
var targetPirate = null;
for (var j = 0; j < pirates.length; j++) {
var p = pirates[j];
@@ -2807,23 +2639,22 @@
npc._aiAttackTimer = 0;
}
}
}
- // Saldırıya geçtiyse, hedefe yaklaş ve ateş et
+ // Attack target pirate if set
if (npc._aiTargetPirate && !npc._aiTargetPirate._destroyed) {
var tp = npc._aiTargetPirate;
var dx = tp.x - npc.x;
var dy = tp.y - npc.y;
var d = Math.sqrt(dx * dx + dy * dy);
- // Yaklaş
+ // Approach
if (d > 120) {
npc.x += dx / d * npc.moveSpeed * 1.2;
npc.y += dy / d * npc.moveSpeed * 1.2;
}
- // Ateş et (her 30 tickte bir)
+ // Shoot (every 30 ticks)
npc._aiAttackTimer = (npc._aiAttackTimer || 0) + 1;
if (d < 300 && npc._aiAttackTimer > 30) {
- // NPC'nin mermisi: Bullet ile aynı, ama _npcBullet=true
var bullet = new Bullet();
bullet.x = npc.x;
bullet.y = npc.y;
var angle = Math.atan2(tp.y - npc.y, tp.x - npc.x);
@@ -2834,9 +2665,8 @@
bullets.push(bullet);
game.addChild(bullet);
npc._aiAttackTimer = 0;
}
- // KILL etiketi gösterme ve kaldırma kodu tamamen kaldırıldı
if (tp.health <= 0 || tp._destroyed) {
npc._aiTargetPirate = null;
}
} else {
@@ -2912,46 +2742,21 @@
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);
- }
- }
+ // No pirate bases, black holes, wormholes, or special buildings
// Spawn entities (star spawn frequency increased 3x)
if (LK.ticks % 33 === 0) {
if (Math.random() < 0.5) {
- // 50% chance
spawnStar();
}
+ // Spawn pirates and NPCs at intervals
+ if (pirates.length < 6 && Math.random() < 0.3) {
+ spawnPirate();
+ }
+ if (npcs.length < 4 && Math.random() < 0.2) {
+ spawnNPC();
+ }
}
// Update score
LK.setScore(playerCoins + questsCompleted * 100 + enemiesKilled * 10 + Math.floor(totalDistance / 100));
if (ship._healthBar && ship._healthBar.update) ship._healthBar.update();
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