User prompt
Görev veren NPC'ye tıkladığımız zaman Karakterin yukarısında Görev hakkında ''Kabul Et - Reddet'' butonları olsun. Ona göre etkileşimde olalım ve ona göre görevi yapalım veya yapmayalım. Verdiğimiz yanıta göre yapay zeka cevap versin ve verdiği görev hakkında işlem yapsın.
User prompt
NPC'ye tıkladığım zaman NPC görevi veya bulunduğum etkileşim Level altında küçük şekilde ve bir süre spawn olsun ve ne konuda etkileşimde bulundum ise bileyim.
User prompt
NPC soru sorduğunda, tıkladığım zaman NPC bir süre dursun.
User prompt
NPC Trade sorusu soruyor. tıkla diyor. Tıklıyorum, ticaret paneli açılmıyor.
User prompt
NPC'ye yaklaşıyorum ama hiçbirşey olmuyor. Ne çıkıyor ise, NPC üzerinde çıksın yaklaşınca.
User prompt
Haritada unsurların spawn olma oranını genel olarak ortalama %10 oranında artır. (Korsanlar hariç)
User prompt
Wave altına, Level ve EXP sistemi ekle, oyundaki RPG görevlerinden EXP kazanalım. RPG Macera oyunu olarak sistemi kur.
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'indexOf')' in or related to this line: 'if (!npcActive && tradeText.text.indexOf("Trade:") !== 0 && tradeText.text.indexOf("Special:") !== 0) {' Line Number: 1428
User prompt
NPC'ler ile ilgili etkileşim kuralım ve birçok RPG ve macera konusu ekle. Bazen de ticaret yapalım. NPC'ler yapay zeka oyuncuları tarafından yönetilsin.
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği veya mekaniği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, Ticaret ve RPG katacak mekanik ve özellik ekle.
User prompt
Haritada unsurların spawn olma oranını genel olarak ortalama %10 oranında artır.
User prompt
''Reduce spawn rate of all entities and asteroids by 80%'' bunu %70 olarak değiştir. Ama korsanlar için %85 olsun. Çünkü korsan çok.
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği veya mekaniği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak mekanik ve özellik ekle.
User prompt
Asteroid'lere de otomatik ateş olsun. Ancak şuan haritada spawn olan unsur oranını %80 oranında azalt. Çok fazla unsur var.
User prompt
Kod içinde olan veya olmayan, oyuna uygun birçok özelliği veya mekaniği aktif et. Uyumsuz ise ekleme. Birbirinden farklı, eğlence katacak mekanik ve özellik ekle.
User prompt
Coins ve hammadde sayıları ekranda görünmüyor. Görünecek şekilde ekranda ki dış alanları sola kaydır.
User prompt
Düşmana, çok yaklaşırsak bize saldırsın ve biz ona çok yaklaşırsak saldıralım. Yoksa normal seyrinde devam etsinler.
User prompt
Haritada ki unsurlar otomatik spawn olma sistemini kaldır. İlerledikçe harita dışından spawn olarak gelsinler veya rastgele dolaşsınlar. sabit durmasın hiç birşey. Bir akış olsun.
User prompt
Harita sürekli aşağı doğru kaymasın, Karakterin gittiği yöne doğru haritada gidelim.
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'healthText.style.fill = "#00ff00";' Line Number: 255
Code edit (1 edits merged)
Please save this source code
User prompt
Galactic Trader: Sonsuz Görevler
Initial prompt
Oyuncu, haritanın merkezinde bir uzay mekiğini joystick ile kontrol eder. Sonsuz bir galakside rastgele NPC’ler belirir ve oyuncuya görevler ile ticaret fırsatları sunar. Korsan savaş gemileriyle karşılaşılır; savaşarak coin ve hammadde toplanır. Toplanan kaynaklar ticaretle satılır, yeni yükseltmeler ve ekipmanlar alınır. Görevler ve ticaret ilerledikçe yeni bölgeler ve zorluklar açılır. Oyun, sonsuz ilerleme ve sürekli gelişen görevlerle devam eder.
/****
* 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;
});
var NPC = Container.expand(function () {
var self = Container.call(this);
var npcGraphics = self.attachAsset('npc', {
anchorX: 0.5,
anchorY: 0.5
});
// --- RPG/Adventure/Trade/AI properties ---
var questTypes = ['trade', 'delivery', 'explore', 'escort', 'hunt', 'puzzle'];
self.questType = questTypes[Math.floor(Math.random() * questTypes.length)];
self.questActive = true;
self.questProgress = 0;
self.questTarget = null;
self.reward = Math.floor(Math.random() * 80) + 30;
self.dialogueStep = 0;
self.hasTraded = false;
self.isAI = true; // AI-driven
self.baseY = 0;
self.moveSpeed = 1 + Math.random() * 2;
self.moveAngle = Math.random() * Math.PI * 2;
self.wanderTimer = 0;
self.lastAIAction = 0;
self.targetX = null;
self.targetY = null;
self.rpgName = "NPC-" + Math.floor(Math.random() * 10000);
self.rpgMood = Math.random() < 0.5 ? "friendly" : "neutral";
self.rpgInventory = {
metal: Math.floor(Math.random() * 10),
energy: Math.floor(Math.random() * 10),
coins: Math.floor(Math.random() * 30)
};
self.rpgTradeOffer = {
give: Math.random() < 0.5 ? "metal" : "energy",
giveAmount: Math.floor(Math.random() * 5) + 1,
want: Math.random() < 0.5 ? "energy" : "metal",
wantAmount: Math.floor(Math.random() * 5) + 1
};
// --- AI/Quest logic ---
self.update = function () {
// Pause logic: If pauseUntil is set and not expired, skip movement
if (self.pauseUntil && LK.ticks < self.pauseUntil) {
// Still paused, only float animation
self.y += Math.sin(LK.ticks * 0.05) * 0.5;
return;
}
// AI: Sometimes move toward a random point, sometimes wander
self.wanderTimer++;
if (self.wanderTimer > 120 + Math.random() * 120) {
if (Math.random() < 0.5) {
// Pick a random point to move toward (simulate AI goal seeking)
self.targetX = self.x + (Math.random() - 0.5) * 800;
self.targetY = self.y + (Math.random() - 0.5) * 800;
} else {
self.targetX = null;
self.targetY = null;
}
self.moveAngle = Math.random() * Math.PI * 2;
self.wanderTimer = 0;
}
// Move toward target if set, else wander
if (self.targetX !== null && self.targetY !== null) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 10) {
self.x += dx / dist * self.moveSpeed;
self.y += dy / dist * self.moveSpeed;
self.moveAngle = Math.atan2(dy, dx);
} else {
self.targetX = null;
self.targetY = null;
}
} else {
self.x += Math.cos(self.moveAngle) * self.moveSpeed;
self.y += Math.sin(self.moveAngle) * self.moveSpeed;
}
// Float animation on top of movement
self.y += Math.sin(LK.ticks * 0.05) * 0.5;
// --- RPG/Quest/Adventure logic: update quest progress if active ---
if (self.questActive && self.questType === 'explore' && self.questTarget) {
// If player is close to quest target, complete quest
var dx = ship.x - self.questTarget.x;
var dy = ship.y - self.questTarget.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 80) {
self.questProgress = 1;
}
}
if (self.questActive && self.questType === 'escort' && self.questTarget) {
// If NPC is close to quest target, complete quest
var dx = self.x - self.questTarget.x;
var dy = self.y - self.questTarget.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 80) {
self.questProgress = 1;
}
}
if (self.questActive && self.questType === 'hunt' && self.questTarget) {
// If quest target pirate is dead, complete quest
if (self.questTarget._destroyed) {
self.questProgress = 1;
}
}
if (self.questActive && self.questType === 'puzzle') {
// Simulate puzzle solved after some time
if (LK.ticks % 600 === 0) {
self.questProgress = 1;
}
}
};
// --- RPG/Adventure/Trade: interaction method for player tap/close ---
self.interact = function () {
// Dialogue/quest/trade logic
if (!self.questActive) return "I'm just exploring the stars!";
// Helper for EXP gain and level up
function gainEXP(amount) {
playerEXP += amount;
var leveledUp = false;
while (playerEXP >= expToNext(playerLevel)) {
playerEXP -= expToNext(playerLevel);
playerLevel++;
leveledUp = true;
}
updateUI();
if (leveledUp) {
LK.effects.flashObject(ship, 0x00ffcc, 800);
return "Level Up! Now Level " + playerLevel + "!";
}
return null;
}
if (self.questType === 'trade') {
if (!self.hasTraded) {
// Offer trade
if (self.rpgTradeOffer.give === 'metal' && playerMetal >= self.rpgTradeOffer.wantAmount) {
playerMetal -= self.rpgTradeOffer.wantAmount;
playerEnergy += self.rpgTradeOffer.giveAmount;
self.hasTraded = true;
var expMsg = gainEXP(10 + Math.floor(Math.random() * 10));
return self.rpgName + ": Thanks for the trade! +" + self.rpgTradeOffer.giveAmount + " energy!" + (expMsg ? "\n" + expMsg : "");
} else if (self.rpgTradeOffer.give === 'energy' && playerEnergy >= self.rpgTradeOffer.wantAmount) {
playerEnergy -= self.rpgTradeOffer.wantAmount;
playerMetal += self.rpgTradeOffer.giveAmount;
self.hasTraded = true;
var expMsg = gainEXP(10 + Math.floor(Math.random() * 10));
return self.rpgName + ": Thanks for the trade! +" + self.rpgTradeOffer.giveAmount + " metal!" + (expMsg ? "\n" + expMsg : "");
} else {
return self.rpgName + ": I can trade " + self.rpgTradeOffer.giveAmount + " " + self.rpgTradeOffer.give + " for " + self.rpgTradeOffer.wantAmount + " " + self.rpgTradeOffer.want + ".";
}
} else {
return self.rpgName + ": Good luck out there!";
}
}
if (self.questType === 'delivery') {
if (self.questProgress === 0) {
// Assign delivery quest: go to a random point
if (!self.questTarget) {
self.questTarget = {
x: self.x + (Math.random() - 0.5) * 2000,
y: self.y + (Math.random() - 0.5) * 2000
};
return self.rpgName + ": Can you deliver this package to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")?";
} else {
var dx = ship.x - self.questTarget.x;
var dy = ship.y - self.questTarget.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 80) {
self.questProgress = 1;
playerCoins += self.reward;
questsCompleted++;
var expMsg = gainEXP(40 + Math.floor(Math.random() * 20));
return self.rpgName + ": Delivery complete! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : "");
} else {
return self.rpgName + ": Please deliver to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")";
}
}
} else {
return self.rpgName + ": Thank you for your help!";
}
}
if (self.questType === 'explore') {
if (self.questProgress === 0) {
if (!self.questTarget) {
self.questTarget = {
x: self.x + (Math.random() - 0.5) * 2000,
y: self.y + (Math.random() - 0.5) * 2000
};
return self.rpgName + ": Can you explore the area at (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")?";
} else {
var dx = ship.x - self.questTarget.x;
var dy = ship.y - self.questTarget.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 80) {
self.questProgress = 1;
playerCoins += self.reward;
questsCompleted++;
var expMsg = gainEXP(30 + Math.floor(Math.random() * 15));
return self.rpgName + ": Thanks for exploring! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : "");
} else {
return self.rpgName + ": Please explore (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")";
}
}
} else {
return self.rpgName + ": You are a true explorer!";
}
}
if (self.questType === 'escort') {
if (self.questProgress === 0) {
if (!self.questTarget) {
self.questTarget = {
x: self.x + (Math.random() - 0.5) * 2000,
y: self.y + (Math.random() - 0.5) * 2000
};
return self.rpgName + ": Can you escort me to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")?";
} else {
var dx = self.x - self.questTarget.x;
var dy = self.y - self.questTarget.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 80) {
self.questProgress = 1;
playerCoins += self.reward;
questsCompleted++;
var expMsg = gainEXP(35 + Math.floor(Math.random() * 15));
return self.rpgName + ": Safe arrival! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : "");
} else {
// Move toward target if player is close
var pdx = ship.x - self.x;
var pdy = ship.y - self.y;
var pdist = Math.sqrt(pdx * pdx + pdy * pdy);
if (pdist < 200) {
var tdx = self.questTarget.x - self.x;
var tdy = self.questTarget.y - self.y;
var tdist = Math.sqrt(tdx * tdx + tdy * tdy);
if (tdist > 10) {
self.x += tdx / tdist * self.moveSpeed;
self.y += tdy / tdist * self.moveSpeed;
}
}
return self.rpgName + ": Please escort me to (" + Math.floor(self.questTarget.x) + "," + Math.floor(self.questTarget.y) + ")";
}
}
} else {
return self.rpgName + ": Thank you for the escort!";
}
}
if (self.questType === 'hunt') {
if (self.questProgress === 0) {
if (!self.questTarget) {
// Assign a random pirate as target
if (pirates.length > 0) {
self.questTarget = pirates[Math.floor(Math.random() * pirates.length)];
return self.rpgName + ": Can you defeat pirate #" + self.questTarget.rpgName + "?";
} else {
return self.rpgName + ": No pirates nearby, come back later!";
}
} else {
if (self.questTarget._destroyed) {
self.questProgress = 1;
playerCoins += self.reward;
questsCompleted++;
var expMsg = gainEXP(50 + Math.floor(Math.random() * 20));
return self.rpgName + ": Pirate defeated! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : "");
} else {
return self.rpgName + ": Please defeat pirate #" + (self.questTarget.rpgName || "unknown");
}
}
} else {
return self.rpgName + ": You are a true hero!";
}
}
if (self.questType === 'puzzle') {
if (self.questProgress === 0) {
return self.rpgName + ": Solve my puzzle! (Wait a bit...)";
} else {
playerCoins += self.reward;
questsCompleted++;
self.questProgress = 2;
var expMsg = gainEXP(25 + Math.floor(Math.random() * 10));
return self.rpgName + ": Puzzle solved! Reward: " + self.reward + " coins!" + (expMsg ? "\n" + expMsg : "");
}
}
return self.rpgName + ": Safe travels!";
};
return self;
});
var Pirate = Container.expand(function () {
var self = Container.call(this);
var pirateGraphics = self.attachAsset('pirate', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.speed = 2;
self.fireRate = 60;
self.lastFire = 0;
self.loot = Math.floor(Math.random() * 30) + 10;
self.moveAngle = Math.random() * Math.PI * 2;
self.patrolTimer = 0;
self.aggroRange = 600;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 100);
};
self.update = function () {
// Movement AI
self.patrolTimer++;
if (self.patrolTimer > 180) {
self.moveAngle = Math.random() * Math.PI * 2;
self.patrolTimer = 0;
}
// Patrol movement
self.x += Math.cos(self.moveAngle) * self.speed * 0.5;
self.y += Math.sin(self.moveAngle) * self.speed * 0.5;
};
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 tradeText = new Text2('', {
size: 40,
fill: 0x00ff99
});
tradeText.anchor.set(0.5, 0);
tradeText.y = 180;
LK.gui.top.addChild(tradeText);
var camera = {
x: 0,
y: 0
};
// 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
var coinText = new Text2('Coins: ' + playerCoins, {
size: 50,
fill: 0xFFFF00
});
coinText.anchor.set(0, 0);
coinText.x = 120;
coinText.y = 20;
LK.gui.topLeft.addChild(coinText);
var resourceText = new Text2('Metal: ' + playerMetal + ' Energy: ' + playerEnergy, {
size: 40,
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: 50,
fill: 0x00FF00
});
healthText.anchor.set(0.5, 0);
LK.gui.top.addChild(healthText);
var shieldText = new Text2('Shield: 50/50', {
size: 40,
fill: 0x0088FF
});
shieldText.anchor.set(0.5, 0);
shieldText.y = 60;
LK.gui.top.addChild(shieldText);
var boostText = new Text2('BOOST READY', {
size: 35,
fill: 0x00FFFF
});
boostText.anchor.set(0.5, 0);
boostText.y = 110;
LK.gui.top.addChild(boostText);
var waveText = new Text2('Wave: 1', {
size: 45,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 0);
waveText.x = -20;
waveText.y = 20;
LK.gui.topRight.addChild(waveText);
// 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: 38,
fill: 0x00ffcc
});
expText.anchor.set(1, 0);
expText.x = -20;
expText.y = 80;
LK.gui.topRight.addChild(expText);
// 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;
// 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;
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;
}
// Scale pirate stats based on wave
pirate.health = 30 + waveNumber * 10;
pirate.damage = 5 + Math.floor(waveNumber / 2);
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;
}
asteroids.push(asteroid);
game.addChild(asteroid);
}
function spawnUpgradeStation() {
var station = new UpgradeStation();
station.x = ship.x + (Math.random() - 0.5) * 3000;
station.y = ship.y + (Math.random() - 0.5) * 3000;
upgradeStations.push(station);
game.addChild(station);
}
function spawnTradeStation() {
var ts = new TradeStation();
// Spawn from edges of visible area
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
ts.x = ship.x + (Math.random() - 0.5) * 2000;
ts.y = ship.y - 1500;
break;
case 1:
ts.x = ship.x + 1500;
ts.y = ship.y + (Math.random() - 0.5) * 2000;
break;
case 2:
ts.x = ship.x + (Math.random() - 0.5) * 2000;
ts.y = ship.y + 1500;
break;
case 3:
ts.x = ship.x - 1500;
ts.y = ship.y + (Math.random() - 0.5) * 2000;
break;
}
tradeStations.push(ts);
game.addChild(ts);
}
function createExplosion(x, y) {
for (var i = 0; i < 8; i++) {
var particle = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
});
particle.vx = (Math.random() - 0.5) * 10;
particle.vy = (Math.random() - 0.5) * 10;
particle.life = 30;
explosions.push(particle);
game.addChild(particle);
}
}
function spawnBlackHole() {
var bh = new BlackHole();
// Spawn far from ship, random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
bh.x = ship.x + (Math.random() - 0.5) * 2000;
bh.y = ship.y - 1700;
break;
case 1:
bh.x = ship.x + 1700;
bh.y = ship.y + (Math.random() - 0.5) * 2000;
break;
case 2:
bh.x = ship.x + (Math.random() - 0.5) * 2000;
bh.y = ship.y + 1700;
break;
case 3:
bh.x = ship.x - 1700;
bh.y = ship.y + (Math.random() - 0.5) * 2000;
break;
}
blackHoles.push(bh);
game.addChild(bh);
}
function spawnWormhole() {
var wh = new Wormhole();
// Spawn far from ship, random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
wh.x = ship.x + (Math.random() - 0.5) * 2000;
wh.y = ship.y - 1700;
break;
case 1:
wh.x = ship.x + 1700;
wh.y = ship.y + (Math.random() - 0.5) * 2000;
break;
case 2:
wh.x = ship.x + (Math.random() - 0.5) * 2000;
wh.y = ship.y + 1700;
break;
case 3:
wh.x = ship.x - 1700;
wh.y = ship.y + (Math.random() - 0.5) * 2000;
break;
}
wormholes.push(wh);
game.addChild(wh);
}
function createBoostParticle() {
var particle = LK.getAsset('boostParticle', {
anchorX: 0.5,
anchorY: 0.5,
x: ship.x - Math.cos(ship.rotation - Math.PI / 2) * 50,
y: ship.y - Math.sin(ship.rotation - Math.PI / 2) * 50
});
particle.vx = -Math.cos(ship.rotation - Math.PI / 2) * 5 + (Math.random() - 0.5) * 2;
particle.vy = -Math.sin(ship.rotation - Math.PI / 2) * 5 + (Math.random() - 0.5) * 2;
particle.life = 20;
boostParticles.push(particle);
game.addChild(particle);
}
function updateUI() {
coinText.setText('Coins: ' + playerCoins);
resourceText.setText('Metal: ' + playerMetal + ' Energy: ' + playerEnergy);
healthText.setText('Health: ' + ship.health + '/' + ship.maxHealth);
shieldText.setText('Shield: ' + Math.floor(ship.shield) + '/' + ship.maxShield);
waveText.setText('Wave: ' + (waveNumber + 1));
expText.setText('Level: ' + playerLevel + ' EXP: ' + playerEXP + '/' + expToNext(playerLevel));
// 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;
}
// Event handlers
game.down = function (x, y, obj) {
if (Math.sqrt(Math.pow(x - joystickBase.x, 2) + Math.pow(y - joystickBase.y, 2)) < 100) {
isDragging = true;
joystickHandle.x = x;
joystickHandle.y = y;
} else if (y < 300 && ship.boostCooldown <= 0) {
// Boost when tapping upper area of screen
ship.boostSpeed = 10;
ship.boostCooldown = 300; // 5 seconds cooldown
if (LK.getSound('boost')) {
LK.getSound('boost').play();
}
} else {
// --- Handle Accept/Reject quest button taps ---
if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) {
var btn = game._questDecisionAcceptBtn;
var bx = btn.x,
by = btn.y;
// Button is about 180x80 px
if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) {
// Accept quest
var npc = btn._questNPC;
if (npc) {
// Mark quest as accepted (progress 1 means started)
npc.questProgress = 1;
// Show NPC response
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;
// Show floating label for accepted
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 response
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);
}
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) {
// Mark quest as inactive
npc.questActive = false;
// 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;
// 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 response
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);
}
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;
}
}
}
};
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
if (LK.ticks - ship.lastFire > ship.fireRate && (pirates.length > 0 || asteroids.length > 0)) {
// Find nearest pirate or asteroid within 200 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 < 200 && 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 < 200 && dist < nearestDistance) {
nearestDistance = dist;
nearestTarget = asteroids[i];
isPirate = false;
}
}
if (nearestTarget) {
var bullet = new Bullet();
bullet.x = ship.x;
bullet.y = ship.y;
var angle = Math.atan2(nearestTarget.y - ship.y, nearestTarget.x - ship.x);
bullet.directionX = Math.cos(angle);
bullet.directionY = Math.sin(angle);
bullet.rotation = angle + Math.PI / 2;
bullets.push(bullet);
game.addChild(bullet);
ship.lastFire = LK.ticks;
LK.getSound('shoot').play();
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check collision with pirates
for (var j = pirates.length - 1; j >= 0; j--) {
if (bullet.intersects(pirates[j])) {
pirates[j].takeDamage(bullet.damage);
if (pirates[j].health <= 0) {
enemiesKilled++;
createExplosion(pirates[j].x, pirates[j].y);
// Drop loot
var coin = new Coin();
coin.x = pirates[j].x;
coin.y = pirates[j].y;
coin.value = coin.value * (1 + Math.floor(waveNumber / 3));
coins.push(coin);
game.addChild(coin);
if (Math.random() < 0.3) {
var resource = new Resource();
resource.x = pirates[j].x + (Math.random() - 0.5) * 50;
resource.y = pirates[j].y + (Math.random() - 0.5) * 50;
resources.push(resource);
game.addChild(resource);
}
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];
// Update pirate AI
var dist = Math.sqrt(Math.pow(ship.x - pirate.x, 2) + Math.pow(ship.y - pirate.y, 2));
// Only chase and attack when very close (within 200 pixels)
if (dist < 200) {
// Chase ship when very close
var angle = Math.atan2(ship.y - pirate.y, ship.x - pirate.x);
pirate.x += Math.cos(angle) * pirate.speed;
pirate.y += Math.sin(angle) * pirate.speed;
pirate.rotation = angle + Math.PI / 2;
// Pirate shooting when very close
if (LK.ticks - pirate.lastFire > pirate.fireRate) {
var bullet = new EnemyBullet();
bullet.x = pirate.x;
bullet.y = pirate.y;
bullet.directionX = Math.cos(angle);
bullet.directionY = Math.sin(angle);
enemyBullets.push(bullet);
game.addChild(bullet);
pirate.lastFire = LK.ticks;
}
}
if (dist > 2000) {
pirate.destroy();
pirates.splice(i, 1);
i--;
}
}
// Update NPCs
var npcActive = false;
for (var i = npcs.length - 1; i >= 0; i--) {
var npc = npcs[i];
// 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;
}
// RPG/Adventure: If player is close, show interaction UI
if (dist < 180) {
npcActive = true;
// Remove any previous floating text
if (npc._npcText && npc._npcText.parent) {
npc._npcText.parent.removeChild(npc._npcText);
npc._npcText = null;
}
var npcMsg = "";
if (game._lastNPCTap !== undefined && game._lastNPCTap + 30 > LK.ticks && game._lastNPC !== npc) {
// Player tapped recently, interact
var msg = npc.interact();
npcMsg = msg;
updateUI();
saveProgress();
game._lastNPC = npc;
// Pause NPC for 2 seconds (120 ticks) after interaction
npc.pauseUntil = LK.ticks + 120;
// Also clear tradeText in GUI
tradeText.setText('');
// --- Show floating interaction label under NPC for a short duration ---
if (msg && typeof msg === "string" && msg.length > 0) {
// Remove previous interaction label if any
if (npc._npcInteractionLabel && npc._npcInteractionLabel.parent) {
npc._npcInteractionLabel.parent.removeChild(npc._npcInteractionLabel);
npc._npcInteractionLabel = null;
}
var interactionLabel = new Text2(msg.split('\n')[0], {
size: 30,
fill: 0xffffff,
align: "center"
});
interactionLabel.anchor.set(0.5, 0);
interactionLabel.x = npc.x;
interactionLabel.y = npc.y + 70;
npc._npcInteractionLabel = interactionLabel;
game.addChild(interactionLabel);
// Set a timer to remove after 2.5 seconds (150 ticks)
npc._npcInteractionLabelExpire = LK.ticks + 150;
}
// --- Show Accept/Reject quest buttons above the ship if NPC is a quest-giver and quest is not yet accepted ---
if (npc.questActive && npc.questType !== 'trade' && npc.questProgress === 0 && !npc._questDecisionPanel) {
// Remove any previous quest panel
if (game._questDecisionPanel && game._questDecisionPanel.parent) {
game._questDecisionPanel.parent.removeChild(game._questDecisionPanel);
game._questDecisionPanel = null;
}
if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) {
game._questDecisionAcceptBtn.parent.removeChild(game._questDecisionAcceptBtn);
game._questDecisionAcceptBtn = null;
}
if (game._questDecisionRejectBtn && game._questDecisionRejectBtn.parent) {
game._questDecisionRejectBtn.parent.removeChild(game._questDecisionRejectBtn);
game._questDecisionRejectBtn = null;
}
// Panel background
var panel = LK.getAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
x: ship.x,
y: ship.y - 180,
scaleX: 7,
scaleY: 2,
tint: 0x222244
});
// Quest text
var questText = new Text2("Görev: " + (npcMsg ? npcMsg.split('\n')[0] : "Bir görev var!"), {
size: 38,
fill: 0xffffff,
align: "center"
});
questText.anchor.set(0.5, 0.5);
questText.x = ship.x;
questText.y = ship.y - 200;
// Accept button
var acceptBtn = new Text2("Kabul Et", {
size: 44,
fill: 0x00ff99,
align: "center"
});
acceptBtn.anchor.set(0.5, 0.5);
acceptBtn.x = ship.x - 100;
acceptBtn.y = ship.y - 120;
// Reject button
var rejectBtn = new Text2("Reddet", {
size: 44,
fill: 0xff4444,
align: "center"
});
rejectBtn.anchor.set(0.5, 0.5);
rejectBtn.x = ship.x + 100;
rejectBtn.y = ship.y - 120;
// Add to game
game.addChild(panel);
game.addChild(questText);
game.addChild(acceptBtn);
game.addChild(rejectBtn);
// Store references for cleanup
npc._questDecisionPanel = panel;
npc._questDecisionText = questText;
npc._questDecisionAcceptBtn = acceptBtn;
npc._questDecisionRejectBtn = rejectBtn;
game._questDecisionPanel = panel;
game._questDecisionAcceptBtn = acceptBtn;
game._questDecisionRejectBtn = rejectBtn;
game._questDecisionText = questText;
game._questDecisionNPC = npc;
// Accept/Reject tap logic
acceptBtn._isQuestAcceptBtn = true;
rejectBtn._isQuestRejectBtn = true;
acceptBtn._questNPC = npc;
rejectBtn._questNPC = npc;
acceptBtn._questType = npc.questType;
rejectBtn._questType = npc.questType;
}
// --- NPC Trade Panel Logic ---
if (npc.questType === 'trade' && npc.questActive && !npc.hasTraded) {
// Show a trade panel above the NPC with offer and tap-to-trade
var offer = npc.rpgTradeOffer;
var canTrade = false;
var tradeMsg = "";
if (offer.give === 'metal' && playerMetal >= offer.wantAmount) {
canTrade = true;
tradeMsg = "Trade: Give " + offer.wantAmount + " " + offer.want + " for " + offer.giveAmount + " " + offer.give + " (Tap to confirm)";
} else if (offer.give === 'energy' && playerEnergy >= offer.wantAmount) {
canTrade = true;
tradeMsg = "Trade: Give " + offer.wantAmount + " " + offer.want + " for " + offer.giveAmount + " " + offer.give + " (Tap to confirm)";
} else {
tradeMsg = "Trade: Need " + offer.wantAmount + " " + offer.want + " to trade for " + offer.giveAmount + " " + offer.give;
}
// Remove previous trade panel if any
if (npc._npcTradePanel && npc._npcTradePanel.parent) {
npc._npcTradePanel.parent.removeChild(npc._npcTradePanel);
npc._npcTradePanel = null;
}
var tradePanel = new Text2(tradeMsg, {
size: 36,
fill: canTrade ? 0x00ff99 : 0xff8888,
align: "center"
});
tradePanel.anchor.set(0.5, 0);
tradePanel.x = npc.x;
tradePanel.y = npc.y + 80;
npc._npcTradePanel = tradePanel;
game.addChild(tradePanel);
// If tapped again within window, perform trade
if (canTrade && game._lastNPCTap !== undefined && game._lastNPCTap + 15 > LK.ticks && game._lastNPCTrade !== npc) {
// Actually perform trade
if (offer.give === 'metal') {
playerMetal -= offer.wantAmount;
playerEnergy += offer.giveAmount;
} else {
playerEnergy -= offer.wantAmount;
playerMetal += offer.giveAmount;
}
npc.hasTraded = true;
var expMsg = "EXP +" + (10 + Math.floor(Math.random() * 10));
playerEXP += 10 + Math.floor(Math.random() * 10);
updateUI();
saveProgress();
// Show confirmation
tradePanel.setText("Trade complete!\n" + expMsg);
tradePanel.fill = 0x00ffcc;
game._lastNPCTrade = npc;
}
} else {
// Remove trade panel if not trading
if (npc._npcTradePanel && npc._npcTradePanel.parent) {
npc._npcTradePanel.parent.removeChild(npc._npcTradePanel);
npc._npcTradePanel = null;
}
}
} else if (!npc.questActive || npc.questProgress > 0) {
npcMsg = npc.rpgName + ": " + (npc.questActive ? "Thank you!" : "Safe travels!");
// Remove trade panel if not trading
if (npc._npcTradePanel && npc._npcTradePanel.parent) {
npc._npcTradePanel.parent.removeChild(npc._npcTradePanel);
npc._npcTradePanel = null;
}
} else {
// Show quest/trade offer
if (npc.questType === 'trade') {
npcMsg = npc.rpgName + ": Trade? Tap to interact.";
} else if (npc.questType === 'delivery') {
npcMsg = npc.rpgName + ": Delivery quest! Tap to interact.";
} else if (npc.questType === 'explore') {
npcMsg = npc.rpgName + ": Exploration quest! Tap to interact.";
} else if (npc.questType === 'escort') {
npcMsg = npc.rpgName + ": Escort quest! Tap to interact.";
} else if (npc.questType === 'hunt') {
npcMsg = npc.rpgName + ": Hunt quest! Tap to interact.";
} else if (npc.questType === 'puzzle') {
npcMsg = npc.rpgName + ": Puzzle quest! Tap to interact.";
}
// Remove trade panel if not trading
if (npc._npcTradePanel && npc._npcTradePanel.parent) {
npc._npcTradePanel.parent.removeChild(npc._npcTradePanel);
npc._npcTradePanel = null;
}
}
// Show floating text above NPC
if (npcMsg) {
var npcText = new Text2(npcMsg, {
size: 38,
fill: 0x00ffcc,
align: "center"
});
npcText.anchor.set(0.5, 1);
npcText.x = npc.x;
npcText.y = npc.y - 70;
// Remove previous if any
if (npc._npcText && npc._npcText.parent) {
npc._npcText.parent.removeChild(npc._npcText);
}
npc._npcText = npcText;
game.addChild(npcText);
}
// Remove tradeText from GUI
tradeText.setText('');
} else {
// Remove floating text if player is not close
if (npc._npcText && npc._npcText.parent) {
npc._npcText.parent.removeChild(npc._npcText);
npc._npcText = null;
}
}
// Remove quest Accept/Reject panel if player moves away from NPC
if (npc._questDecisionPanel && dist >= 220) {
if (npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel);
if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText);
if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn);
if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn);
npc._questDecisionPanel = null;
npc._questDecisionText = null;
npc._questDecisionAcceptBtn = null;
npc._questDecisionRejectBtn = null;
game._questDecisionPanel = null;
game._questDecisionAcceptBtn = null;
game._questDecisionRejectBtn = null;
game._questDecisionText = null;
game._questDecisionNPC = null;
}
// Remove floating interaction label if expired
if (npc._npcInteractionLabel && npc._npcInteractionLabelExpire !== undefined && LK.ticks > npc._npcInteractionLabelExpire) {
if (npc._npcInteractionLabel.parent) {
npc._npcInteractionLabel.parent.removeChild(npc._npcInteractionLabel);
}
npc._npcInteractionLabel = null;
npc._npcInteractionLabelExpire = undefined;
}
}
if (!npcActive) {
game._lastNPC = null;
}
// Update asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
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 upgrade stations
for (var i = upgradeStations.length - 1; i >= 0; i--) {
var station = upgradeStations[i];
var dist = Math.sqrt(Math.pow(station.x - ship.x, 2) + Math.pow(station.y - ship.y, 2));
if (dist < 100 && playerCoins >= 100) {
// Apply random upgrade
var upgrade = station.upgrades[Math.floor(Math.random() * station.upgrades.length)];
if (upgrade.name === 'health' && playerMetal >= (upgrade.metalCost || 0)) {
ship.maxHealth += 20;
ship.health = ship.maxHealth;
playerCoins -= upgrade.cost;
playerMetal -= upgrade.metalCost || 0;
} else if (upgrade.name === 'shield' && playerMetal >= (upgrade.metalCost || 0)) {
ship.maxShield += 10;
ship.shield = ship.maxShield;
playerCoins -= upgrade.cost;
playerMetal -= upgrade.metalCost || 0;
} else if (upgrade.name === 'damage' && playerEnergy >= (upgrade.energyCost || 0)) {
ship.damage += 5;
playerCoins -= upgrade.cost;
playerEnergy -= upgrade.energyCost || 0;
} else if (upgrade.name === 'speed' && playerEnergy >= (upgrade.energyCost || 0)) {
ship.speed += 1;
playerCoins -= upgrade.cost;
playerEnergy -= upgrade.energyCost || 0;
}
if (LK.getSound('upgrade')) {
LK.getSound('upgrade').play();
}
updateUI();
saveProgress();
station.destroy();
upgradeStations.splice(i, 1);
}
if (dist > 3000) {
station.destroy();
upgradeStations.splice(i, 1);
}
}
// Update boost particles
for (var i = boostParticles.length - 1; i >= 0; i--) {
var particle = boostParticles[i];
particle.x += particle.vx;
particle.y += particle.vy;
particle.life--;
particle.alpha = particle.life / 20;
if (particle.life <= 0) {
particle.destroy();
boostParticles.splice(i, 1);
}
}
// Update explosion particles
for (var i = explosions.length - 1; i >= 0; i--) {
var particle = explosions[i];
particle.x += particle.vx;
particle.y += particle.vy;
particle.vx *= 0.9;
particle.vy *= 0.9;
particle.life--;
particle.alpha = particle.life / 30;
particle.scaleX = particle.scaleY = 1 + (30 - particle.life) / 10;
if (particle.life <= 0) {
particle.destroy();
explosions.splice(i, 1);
}
}
// Collect items
for (var i = coins.length - 1; i >= 0; i--) {
if (coins[i].intersects(ship)) {
playerCoins += coins[i].value;
coins[i].destroy();
coins.splice(i, 1);
LK.getSound('collect').play();
updateUI();
saveProgress();
}
}
for (var i = resources.length - 1; i >= 0; i--) {
if (resources[i].intersects(ship)) {
if (resources[i].type === 'metal') {
playerMetal += resources[i].amount;
} else {
playerEnergy += resources[i].amount;
}
resources[i].destroy();
resources.splice(i, 1);
LK.getSound('collect').play();
updateUI();
saveProgress();
}
}
// Update stars
for (var i = stars.length - 1; i >= 0; i--) {
var dist = Math.sqrt(Math.pow(stars[i].x - ship.x, 2) + Math.pow(stars[i].y - ship.y, 2));
if (dist > 2000) {
stars[i].destroy();
stars.splice(i, 1);
}
}
// Update black holes
for (var i = blackHoles.length - 1; i >= 0; i--) {
var bh = blackHoles[i];
if (bh.update) bh.update();
var dist = Math.sqrt(Math.pow(bh.x - ship.x, 2) + Math.pow(bh.y - ship.y, 2));
if (dist > 3000) {
bh.destroy();
blackHoles.splice(i, 1);
}
}
// Update wormholes
for (var i = wormholes.length - 1; i >= 0; i--) {
var wh = wormholes[i];
if (wh.update) wh.update();
var dist = Math.sqrt(Math.pow(wh.x - ship.x, 2) + Math.pow(wh.y - ship.y, 2));
if (dist > 3000) {
wh.destroy();
wormholes.splice(i, 1);
}
}
// Update trade stations (RPG/ticaret)
var tradeActive = false;
for (var i = tradeStations.length - 1; i >= 0; i--) {
var ts = tradeStations[i];
if (ts.update) ts.update();
var dist = Math.sqrt(Math.pow(ts.x - ship.x, 2) + Math.pow(ts.y - ship.y, 2));
if (dist < 180) {
tradeActive = true;
// Show trade offer
if (ts.specialOffer && ts.specialUpgrade) {
tradeText.setText('Special: ' + ts.specialUpgrade.label + ' for ' + ts.specialUpgrade.cost + ' coins\n(Tap to buy)');
// Buy special upgrade on tap
if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) {
if (playerCoins >= ts.specialUpgrade.cost) {
playerCoins -= ts.specialUpgrade.cost;
if (ts.specialUpgrade.name === 'maxHealth') {
ship.maxHealth += 30;
ship.health = ship.maxHealth;
} else if (ts.specialUpgrade.name === 'maxShield') {
ship.maxShield += 20;
ship.shield = ship.maxShield;
} else if (ts.specialUpgrade.name === 'damage') {
ship.damage += 5;
} else if (ts.specialUpgrade.name === 'speed') {
ship.speed += 1;
}
LK.effects.flashObject(ship, 0x00ff99, 400);
updateUI();
saveProgress();
ts.destroy();
tradeStations.splice(i, 1);
tradeText.setText('Upgrade purchased!');
game._lastTradeStation = null;
break;
} else {
tradeText.setText('Not enough coins!');
}
}
} else if (ts.offerType === 'buy') {
tradeText.setText('Trade: Sell ' + ts.amount + ' ' + ts.resourceType + ' for ' + ts.price + ' coins\n(Tap to sell)');
// Sell resource on tap
if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) {
if (ts.resourceType === 'metal' && playerMetal >= ts.amount) {
playerMetal -= ts.amount;
playerCoins += ts.price;
LK.effects.flashObject(ship, 0x00ff99, 200);
updateUI();
saveProgress();
ts.destroy();
tradeStations.splice(i, 1);
tradeText.setText('Sold!');
game._lastTradeStation = null;
break;
} else if (ts.resourceType === 'energy' && playerEnergy >= ts.amount) {
playerEnergy -= ts.amount;
playerCoins += ts.price;
LK.effects.flashObject(ship, 0x00ff99, 200);
updateUI();
saveProgress();
ts.destroy();
tradeStations.splice(i, 1);
tradeText.setText('Sold!');
game._lastTradeStation = null;
break;
} else {
tradeText.setText('Not enough ' + ts.resourceType + '!');
}
}
} else if (ts.offerType === 'sell') {
tradeText.setText('Trade: Buy ' + ts.amount + ' ' + ts.resourceType + ' for ' + ts.price + ' coins\n(Tap to buy)');
// Buy resource on tap
if (game._lastTradeStation !== ts && game._lastTradeStationTap !== undefined && game._lastTradeStationTap + 30 > LK.ticks) {
if (playerCoins >= ts.price) {
playerCoins -= ts.price;
if (ts.resourceType === 'metal') {
playerMetal += ts.amount;
} else {
playerEnergy += ts.amount;
}
LK.effects.flashObject(ship, 0x00ff99, 200);
updateUI();
saveProgress();
ts.destroy();
tradeStations.splice(i, 1);
tradeText.setText('Purchased!');
game._lastTradeStation = null;
break;
} else {
tradeText.setText('Not enough coins!');
}
}
}
game._lastTradeStation = ts;
}
if (dist > 2500) {
ts.destroy();
tradeStations.splice(i, 1);
}
}
if (!tradeActive) {
tradeText.setText('');
game._lastTradeStation = null;
}
// Spawn entities (reduced by 70%)
if (LK.ticks % 100 === 0) {
if (Math.random() < 0.5) {
// 50% chance
spawnStar();
}
}
// Spawn black holes occasionally
if (LK.ticks % 3600 === 0 && Math.random() < 0.6) {
spawnBlackHole();
}
// Spawn wormholes occasionally
if (LK.ticks % 4200 === 0 && Math.random() < 0.6) {
spawnWormhole();
}
// Spawn trade stations occasionally (RPG/ticaret)
if (LK.ticks % 4800 === 0 && Math.random() < 0.6) {
spawnTradeStation();
}
if (LK.ticks % 900 === 0) {
var spawnRoll = Math.random();
if (spawnRoll < 0.15) {
// 15% chance (pirates reduced by 85%)
spawnPirate();
} else if (spawnRoll < 0.31) {
// 16% chance (NPCs increased by 10%)
spawnNPC();
} else if (spawnRoll < 0.33) {
// 2% chance
// Spawn multiple entities occasionally
spawnPirate();
spawnNPC();
}
}
// Spawn asteroids (reduced by 70%)
if (LK.ticks % 1500 === 0) {
if (Math.random() < 0.5) {
// 50% chance
spawnAsteroid();
}
}
// Wave-based pirate spawning
if (LK.ticks % (180 - Math.min(waveNumber * 10, 100)) === 0) {
var piratesInWave = 1 + Math.floor(waveNumber / 2);
for (var j = 0; j < piratesInWave; j++) {
spawnPirate();
}
}
// Boss wave every 5 waves
if (waveNumber > 0 && waveNumber % 5 === 0 && pirates.length === 0) {
var bossPirate = new Pirate();
bossPirate.x = ship.x + 1000;
bossPirate.y = ship.y;
bossPirate.health = 200 + waveNumber * 20;
bossPirate.damage = 10 + waveNumber;
bossPirate.loot = 200 + waveNumber * 50;
bossPirate.speed = 3;
var bossGraphics = bossPirate.children[0];
bossGraphics.tint = 0xff00ff;
bossGraphics.scaleX = 2;
bossGraphics.scaleY = 2;
pirates.push(bossPirate);
game.addChild(bossPirate);
}
// Update score
LK.setScore(playerCoins + questsCompleted * 100 + enemiesKilled * 10 + Math.floor(totalDistance / 100));
updateUI();
}; ===================================================================
--- original.js
+++ change.js
@@ -1147,8 +1147,114 @@
if (LK.getSound('boost')) {
LK.getSound('boost').play();
}
} else {
+ // --- Handle Accept/Reject quest button taps ---
+ if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) {
+ var btn = game._questDecisionAcceptBtn;
+ var bx = btn.x,
+ by = btn.y;
+ // Button is about 180x80 px
+ if (x > bx - 90 && x < bx + 90 && y > by - 40 && y < by + 40) {
+ // Accept quest
+ var npc = btn._questNPC;
+ if (npc) {
+ // Mark quest as accepted (progress 1 means started)
+ npc.questProgress = 1;
+ // Show NPC response
+ 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;
+ // Show floating label for accepted
+ 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 response
+ 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);
+ }
+ 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) {
+ // Mark quest as inactive
+ npc.questActive = false;
+ // 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;
+ // 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 response
+ 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);
+ }
+ 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));
@@ -1453,8 +1559,83 @@
game.addChild(interactionLabel);
// Set a timer to remove after 2.5 seconds (150 ticks)
npc._npcInteractionLabelExpire = LK.ticks + 150;
}
+ // --- Show Accept/Reject quest buttons above the ship if NPC is a quest-giver and quest is not yet accepted ---
+ if (npc.questActive && npc.questType !== 'trade' && npc.questProgress === 0 && !npc._questDecisionPanel) {
+ // Remove any previous quest panel
+ if (game._questDecisionPanel && game._questDecisionPanel.parent) {
+ game._questDecisionPanel.parent.removeChild(game._questDecisionPanel);
+ game._questDecisionPanel = null;
+ }
+ if (game._questDecisionAcceptBtn && game._questDecisionAcceptBtn.parent) {
+ game._questDecisionAcceptBtn.parent.removeChild(game._questDecisionAcceptBtn);
+ game._questDecisionAcceptBtn = null;
+ }
+ if (game._questDecisionRejectBtn && game._questDecisionRejectBtn.parent) {
+ game._questDecisionRejectBtn.parent.removeChild(game._questDecisionRejectBtn);
+ game._questDecisionRejectBtn = null;
+ }
+ // Panel background
+ var panel = LK.getAsset('resource', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: ship.x,
+ y: ship.y - 180,
+ scaleX: 7,
+ scaleY: 2,
+ tint: 0x222244
+ });
+ // Quest text
+ var questText = new Text2("Görev: " + (npcMsg ? npcMsg.split('\n')[0] : "Bir görev var!"), {
+ size: 38,
+ fill: 0xffffff,
+ align: "center"
+ });
+ questText.anchor.set(0.5, 0.5);
+ questText.x = ship.x;
+ questText.y = ship.y - 200;
+ // Accept button
+ var acceptBtn = new Text2("Kabul Et", {
+ size: 44,
+ fill: 0x00ff99,
+ align: "center"
+ });
+ acceptBtn.anchor.set(0.5, 0.5);
+ acceptBtn.x = ship.x - 100;
+ acceptBtn.y = ship.y - 120;
+ // Reject button
+ var rejectBtn = new Text2("Reddet", {
+ size: 44,
+ fill: 0xff4444,
+ align: "center"
+ });
+ rejectBtn.anchor.set(0.5, 0.5);
+ rejectBtn.x = ship.x + 100;
+ rejectBtn.y = ship.y - 120;
+ // Add to game
+ game.addChild(panel);
+ game.addChild(questText);
+ game.addChild(acceptBtn);
+ game.addChild(rejectBtn);
+ // Store references for cleanup
+ npc._questDecisionPanel = panel;
+ npc._questDecisionText = questText;
+ npc._questDecisionAcceptBtn = acceptBtn;
+ npc._questDecisionRejectBtn = rejectBtn;
+ game._questDecisionPanel = panel;
+ game._questDecisionAcceptBtn = acceptBtn;
+ game._questDecisionRejectBtn = rejectBtn;
+ game._questDecisionText = questText;
+ game._questDecisionNPC = npc;
+ // Accept/Reject tap logic
+ acceptBtn._isQuestAcceptBtn = true;
+ rejectBtn._isQuestRejectBtn = true;
+ acceptBtn._questNPC = npc;
+ rejectBtn._questNPC = npc;
+ acceptBtn._questType = npc.questType;
+ rejectBtn._questType = npc.questType;
+ }
// --- NPC Trade Panel Logic ---
if (npc.questType === 'trade' && npc.questActive && !npc.hasTraded) {
// Show a trade panel above the NPC with offer and tap-to-trade
var offer = npc.rpgTradeOffer;
@@ -1564,8 +1745,24 @@
npc._npcText.parent.removeChild(npc._npcText);
npc._npcText = null;
}
}
+ // Remove quest Accept/Reject panel if player moves away from NPC
+ if (npc._questDecisionPanel && dist >= 220) {
+ if (npc._questDecisionPanel.parent) npc._questDecisionPanel.parent.removeChild(npc._questDecisionPanel);
+ if (npc._questDecisionText && npc._questDecisionText.parent) npc._questDecisionText.parent.removeChild(npc._questDecisionText);
+ if (npc._questDecisionAcceptBtn && npc._questDecisionAcceptBtn.parent) npc._questDecisionAcceptBtn.parent.removeChild(npc._questDecisionAcceptBtn);
+ if (npc._questDecisionRejectBtn && npc._questDecisionRejectBtn.parent) npc._questDecisionRejectBtn.parent.removeChild(npc._questDecisionRejectBtn);
+ npc._questDecisionPanel = null;
+ npc._questDecisionText = null;
+ npc._questDecisionAcceptBtn = null;
+ npc._questDecisionRejectBtn = null;
+ game._questDecisionPanel = null;
+ game._questDecisionAcceptBtn = null;
+ game._questDecisionRejectBtn = null;
+ game._questDecisionText = null;
+ game._questDecisionNPC = null;
+ }
// Remove floating interaction label if expired
if (npc._npcInteractionLabel && npc._npcInteractionLabelExpire !== undefined && LK.ticks > npc._npcInteractionLabelExpire) {
if (npc._npcInteractionLabel.parent) {
npc._npcInteractionLabel.parent.removeChild(npc._npcInteractionLabel);
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