User prompt
and spawn kilifbos 20 pixels right of kilif assets spawnpoint
User prompt
make kilifbos %10 smaller
User prompt
after gun leave holster replace kilif asset with kilifbos
Code edit (7 edits merged)
Please save this source code
User prompt
put kilif instead of holstervisuals
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
function setupAmmoUI() { ... // ─── Y EKSI / ARTI KAYMALAR ─────────────────────────── - bulletP.y = player.y + 250; // eski konum - bulletE.y = enemy.y - 250; // " + bulletP.y = player.y + 250 + 60; // oyuncu: 60 px aşağı + + // Düşman: yalnızca 5. raundda 75 px yukarı + var enemyExtraY = (roundNum === 5) ? -75 : 0; + bulletE.y = enemy.y - 250 + enemyExtraY; // ────────────────────────────────────────────────────── ... } Oyuncu (bulletP): +60 px ekleyerek ikonları ekranda biraz aşağı indiriyoruz. Düşman (bulletE): Normalde aynı yerde kalır; ancak 5. raundda enemyExtraY = -75 ile 75 px yukarı kaydırılır.
User prompt
aimEnemyGunAt düzeltmesi — sadece şu dört satırı değiştiriyoruz diff Kopyala Düzenle function aimEnemyGunAt(globalX, globalY) { ... // 1-2 aynı - var armRot = ang + Math.PI / 2; // ⟵ YANLIŞ + var armRot = ang - Math.PI / 2; // ⟵ DOĞRU enemy.rarm.rotation = armRot; var L = enemy.rarm.height; // ≈145 px - enemy.gun.x = enemy.rarm.x + Math.sin(armRot) * L; // ⟵ YANLIŞ - enemy.gun.y = enemy.rarm.y - Math.cos(armRot) * L; // ⟵ YANLIŞ + enemy.gun.x = enemy.rarm.x - Math.sin(armRot) * L; // ⟵ DOĞRU + enemy.gun.y = enemy.rarm.y + Math.cos(armRot) * L; // ⟵ DOĞRU enemy.gun.rotation = ang; } armRot = ang − π/2 → kolun aşağı başlangıç açısını telafi eder. El-silah ofsetinde (-sin, +cos) kullanıyoruz; bu da aşağıdan yukarı doğru L kadar taşıyor ve karakter hangi tarafta durursa dursun tabancayı elin ucuna tam oturtuyor.
User prompt
/**** GLOBAL : Enemy silahını hedefe çevir ****/ function aimEnemyGunAt(globalX, globalY) { // 1) Omuz pivotu (world) var shX = enemy.x + enemy.rarm.x; var shY = enemy.y + enemy.rarm.y; // 2) Omuz→hedef vektörü var dx = globalX - shX; var dy = globalY - shY; var ang = Math.atan2(dy, dx); // 3) Kol sprite’ı AŞAĞI bakıyor → +90° (+π/2) çevrim var armRot = ang + Math.PI / 2; enemy.rarm.rotation = armRot; // 4) El / silah konumu (enemy LOCAL) **ayna!** var L = enemy.rarm.height; // ≈145 px enemy.gun.x = enemy.rarm.x + Math.sin(armRot) * L; enemy.gun.y = enemy.rarm.y - Math.cos(armRot) * L; // 5) Namluyu hedefe döndür enemy.gun.rotation = ang; } Not: Oyuncuda -Math.sin / +Math.cos kullanmıştık; sağ-sol ayna sebebiyle burada +sin / -cos olmalı. 2. Ne zaman çağıracağız? Çiz (“DRAW!”) anında – silah kılıftan çıkınca hemen hizalansın Ateş etmeden hemen önce – garanti olsun (İsterseniz game.update içinde de çağırarak sürekli takip ettirebilirsiniz.) diff Kopyala Düzenle @@ function startDraw() { player.toHand(); enemy.toHand(); + aimEnemyGunAt(player.x, player.y - 40); // hemen hizala @@ function enemyFire() { + // Ateşten önce hedefe çevir + aimEnemyGunAt(player.x, player.y - 40); 3. (Ekstra) Sürekli takip ettirmek isterseniz diff Kopyala Düzenle game.update = function (dt) { ... + // Rakip silahı eldeyse oyuncuyu takip etsin + if (enemy.gun.visible) { + aimEnemyGunAt(player.x, player.y - 40); + } }
User prompt
Tek yapmanız gereken bu sprite’ı baştan 90 ° döndürmek (ve mümkünse pivotu ortalamak). Aşağıdaki minik yama hem oyuncu hem de düşman tarafını düzeltir. diff Kopyala Düzenle @@ // PLAYER -------------------------------------------------- - var hipGun = self.attachAsset('playerGun', { - anchorX: 0, - anchorY: 0.5, - x: body.width / 2 + 8, - y: body.height / 2 - 22, - rotation: 0 - }); + var hipGun = self.attachAsset('playerGun', { + anchorX: 0.5, // merkezden döndür + anchorY: 0.5, + x: body.width / 2 + 8, // konum aynı + y: body.height / 2 - 22, + rotation: Math.PI / 2 // ↓ aşağı baksın + }); @@ // ENEMY --------------------------------------------------- - var hipGun = self.attachAsset('enemyGun', { - anchorX: 0, - anchorY: 0.5, - x: body.width / 2 + 8, - y: body.height / 2 - 22, - rotation: 0 - }); + var hipGun = self.attachAsset('enemyGun', { + anchorX: 0.5, + anchorY: 0.5, + x: body.width / 2 + 8, + y: body.height / 2 - 22, + rotation: Math.PI / 2 + });
User prompt
Aşağı bakan bir sprite’ı (yani default vektörü (0, +L)) armRot kadar döndürürseniz doğru dönüşüm formülü şu olur ⬇️ cpp Kopyala Düzenle x' = -L · sin(θ) y' = L · cos(θ) 1 — pointGunAt() fonksiyonunu düzelt js Kopyala Düzenle function pointGunAt(globalX, globalY) { const shX = player.x + player.rarm.x; const shY = player.y + player.rarm.y; const dx = globalX - shX; const dy = globalY - shY; const ang = Math.atan2(dy, dx); // Kol 0° iken aşağı bakıyor ⇒ –90° düzeltme const armRot = ang - Math.PI / 2; player.rarm.rotation = armRot; const L = player.rarm.height; // ❗️ Doğru ofset: (-sin, +cos) player.gun.x = player.rarm.x - Math.sin(armRot) * L; player.gun.y = player.rarm.y + Math.cos(armRot) * L; // Namlu yönü if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta namlu aşağı } else { player.gun.rotation = ang; // hedefe bak } } Aynı formülü kullanarak enemy tarafındaki pointGunAt benzeri kod varsa orayı da güncelle. 2 — Mermi çıkış noktası (isteğe bağlı) Mermi doğuş konumunu hesaplarken de silahın merkez ankrajını kullandığımızdan sıkıntı yok; ama “tam namlu ucu olsun” istiyorsanız silah uzunluğunun yarısı yerine tam uzunluğu kullanabilirsiniz: js Kopyala Düzenle const gunLen = player.gun.width; // 60 px x + Math.cos(player.gun.rotation) * gunLen y + Math.sin(player.gun.rotation) * gunLen
User prompt
1. Silah sprite’larının ankrajını düzelt Hem oyuncuda hem düşmanda elindeki silah için: js Kopyala Düzenle // --- Player class içinde --- var gun = self.attachAsset('playerGun', { anchorX: 0.5, // 0 yerine 0.5 anchorY: 0.5, x: rarm.x, y: rarm.y + rarm.height, rotation: 0 }); // --- Enemy class içinde --- var gun = self.attachAsset('enemyGun', { anchorX: 0.5, // 0 yerine 0.5 anchorY: 0.5, x: rarm.x, y: rarm.y + rarm.height, rotation: 0 }); Holster (beldeki) silahların anchorX’i 0 kalabilir çünkü onlar yatay duruyor ve hizaları zaten kenara göre ayarlanmış. 2. pointGunAt fonksiyonunu eski denkleme döndür Ankraj tekrar merkeze alınınca, kol ucuna düşen noktayı şöyle hesaplayın: js Kopyala Düzenle function pointGunAt(globalX, globalY) { const shX = player.x + player.rarm.x; const shY = player.y + player.rarm.y; const dx = globalX - shX; const dy = globalY - shY; const ang = Math.atan2(dy, dx); // Kol sprite’ı AŞAĞI baktığı için –90° düzeltme const armRot = ang - Math.PI / 2; player.rarm.rotation = armRot; // === kolun bittiği noktaya silahın MERKEZİNİ yerleştir === const L = player.rarm.height; player.gun.x = player.rarm.x + Math.sin(armRot) * L; player.gun.y = player.rarm.y - Math.cos(armRot) * L; // Namlu yönü if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta namlu aşağı } else { player.gun.rotation = ang; // hedefe bak } } Not: Math.sin-Math.cos sıralaması kolun dik duruşuna göre (aşağı bakıyor) doğru vektörü verir; merkez ankrajla tam oturur. 3. Mermi çıkış noktası (muzzle) için de aynı mantığı kullan js Kopyala Düzenle function muzzlePos() { return { x: player.x + player.gun.x + Math.cos(player.gun.rotation) * 30, // yarım silah boyu y: player.y + player.gun.y + Math.sin(player.gun.rotation) * 15 }; } (merkez ankraj olduğundan 30 px/15 px değerleri silah ölçüsünün yarısıdır; istersen tam en / 2 & yükseklik / 2 ile hesaplayabilirsin.)
User prompt
Çözüm – fonksiyonu bir kez tanımlayıp global scope’ta (dosyada üst seviyede) kullan: js Kopyala Düzenle /**** GLOBAL YARDIMCI : Silahı imlece çevir ****/ function pointGunAt(globalX, globalY) { /* 1) Omuz pivotu – dünya koordinatı */ const shX = player.x + player.rarm.x; const shY = player.y + player.rarm.y; /* 2) Omuz → imleç vektörü ve açı (0 rad = sağ) */ const dx = globalX - shX; const dy = globalY - shY; const ang = Math.atan2(dy, dx); /* 3) Kol sprite’ı AŞAĞI bakıyor → –90° (-π/2) düzelt */ const armRot = ang - Math.PI / 2; player.rarm.rotation = armRot; /* 4) El / silah konumu (player LOCAL) */ const L = player.rarm.height; // ≈110 px player.gun.x = player.rarm.x + Math.cos(armRot) * L; player.gun.y = player.rarm.y + Math.sin(armRot) * L; /* 5) Silah namlu yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // hedefe bak } } 1️⃣ Bu tanımı, game.down / game.move bölümlerinin önüne (örn. tüm game.* tanımlarından hemen önce) yerleştir. 2️⃣ game.move içindeki fazladan (ve hatta iki kez kopyalanmış) pointGunAt tanımlarını sil ve yalnızca global fonksiyonu çağır: js Kopyala Düzenle game.move = function (x, y, obj) { ... // Namlu her zaman fareyi izlesin pointGunAt(x, y); }; 3️⃣ game.down kısmında zaten çağrın var; hata bu değişiklikle gider: js Kopyala Düzenle game.down = function (x, y, obj) { if (zoomFinished && !duelStarted && holsterBox.contains(x, y)) { playerReady = true; holdingHolster = true; player.toHand(); pointGunAt(x, y); // artık global ve erişilebilir beginHold(); return; } ... };
User prompt
Please fix the bug: 'Uncaught ReferenceError: pointGunAt is not defined' in or related to this line: 'pointGunAt(x, y); // silahı anında hizala' Line Number: 873
User prompt
En pratik düzeltme → game.down içindeki holster‐tıklama bloğuna hemen ardından bir kez pointGunAt çağırmak. js Kopyala Düzenle game.down = function (x, y, obj) { // holster’a basıldıysa... if (zoomFinished && !duelStarted && holsterBox.contains(x, y)) { playerReady = true; holdingHolster = true; player.toHand(); // silahı ele al pointGunAt(x, y); // <<< EKLE — silahı anında hizala beginHold(); return; } ... }; Silah artık “hold” tuşlamasıyla anında kolun ucuna oturur.
User prompt
mevcut pointGunAt fonksiyonunda yalnızca iki satırı değiştirmen yeterli. (Arm rotasyonu ve imleç takibi zaten doğru; yalnızca silahın kol-ucu konumunu yeniden hesaplıyoruz.) js Kopyala Düzenle // 4) El / silah konumu (kolun tam ucu) — player LOKALine yaz const L = player.rarm.height; // ≈ 110 px /* ⇩ SADECE BU İKİ SATIRI DEĞİŞTİR ⇩ */ player.gun.x = player.rarm.x + Math.cos(armRot) * L; player.gun.y = player.rarm.y + Math.sin(armRot) * L; Önceki denemede sin ve -cos kullandığımız için silah 90 ° kaymıştı; burada klasik (cos, sin) çiftine dönünce namlu yine kolun tam ucunda kalıyor. Ek olarak, Player ve Enemy sınıflarında silah sprite’ının anchorX / anchorY değerleri hâlâ 0, 0.5 (namlu “sağa” bakacak biçimde) olmalı: js Kopyala Düzenle var gun = self.attachAsset('playerGun', { anchorX: 0, // 0.5 yerine 0 anchorY: 0.5, ... });
User prompt
Aşağıdaki fonksiyonu, şu anda kullandığın pointGunAt’ın üstüne aynen yapıştır: js Kopyala Düzenle // game.move içindeki yardımcı — GLOBAL koordinat alır function pointGunAt(globalX, globalY) { /* 1) Omuz pivotunu DÜNYA (global) uzayında hesapla */ const shX = player.x + player.rarm.x; const shY = player.y + player.rarm.y; /* 2) Omuz-imleç vektörü ve açı (0 rad = sağ) */ const dx = globalX - shX; const dy = globalY - shY; const ang = Math.atan2(dy, dx); /* 3) Kol sprite’ı AŞAĞI baktığı için **-90° (-π/2)** düzeltme */ const armRot = ang - Math.PI / 2; // <<<< tek değişiklik player.rarm.rotation = armRot; /* 4) El / silah konumu (kolun tam ucu) — player LOKALine yaz */ const L = player.rarm.height; // ≈ 110 px player.gun.x = player.rarm.x + Math.sin(armRot) * L; player.gun.y = player.rarm.y - Math.cos(armRot) * L; /* 5) Silah yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // normalde imleci göster } }
User prompt
Aşağıdaki fonksiyonu yine eskisinin yerine kopyala; artık omuz nereye giderse gitsin kol doğru noktayı merkez alır. js Kopyala Düzenle // game.move içindeki yardımcı — GLOBAL koordinat alır function pointGunAt(globalX, globalY) { /* 1) Omuz pivotunu DÜNYA (global) uzayında hesapla */ const shX = player.x + player.rarm.x; // player container offset + kol local x const shY = player.y + player.rarm.y; // » + kol local y /* 2) Omuz-imleç vektörü ve açı (0 rad = sağ) */ const dx = globalX - shX; const dy = globalY - shY; const ang = Math.atan2(dy, dx); /* 3) Kol sprite’ı başlangıçta AŞAĞI baktığı için +90° ekle */ const armRot = ang + Math.PI / 2; player.rarm.rotation = armRot; /* 4) El / silah konumu (kolun tam ucu) — player LOKALine yazıyoruz */ const L = player.rarm.height; // ≈ 110 px player.gun.x = player.rarm.x + Math.sin(armRot) * L; player.gun.y = player.rarm.y - Math.cos(armRot) * L; // -cos → local y aşağı pozitif /* 5) Silah yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // aksi hâlde namlu imleci gösterir } }
User prompt
Aşağıdaki fonksiyonu mevcut pointGunAt fonksiyonunu SİLİP yerine aynen yapıştır — başka satıra dokunmana gerek yok: js Kopyala Düzenle // game.move içindeki yardımcı — GLOBAL koordinat alır function pointGunAt(globalX, globalY) { /* 1) İmleci Player konteynerine çevir */ const p = player.toLocal({ x: globalX, y: globalY }); const sx = player.rarm.x; // omuz (player local) const sy = player.rarm.y; const dx = p.x - sx; const dy = p.y - sy; const ang = Math.atan2(dy, dx); // 0 rad = sağ (doğu) /* 2) Kol dönüşü Sprite BAŞLANGIÇTA YUKARI bakıyorsa –90° (–π/2) ekle */ const armRot = ang - Math.PI / 2; player.rarm.rotation = armRot; /* 3) El / silah konumu (kol sprite’ının alt ucu) */ const L = player.rarm.height; // ≈ 110 px player.gun.x = sx + Math.cos(armRot) * L; player.gun.y = sy + Math.sin(armRot) * L; /* 4) Silah yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // imleç yönü } }
User prompt
Aşağıdaki fonksiyon eski pointGunAt yerine geçsin; başka yere dokunma. (Enemy tarafında da aynı fonksiyon varsa bire-bir kopyala.) js Kopyala Düzenle // game.move içindeki yardımcı — GLOBAL koordinat alır function pointGunAt(globalX, globalY) { /* 1) Omuz pivotunu DÜNYA (global) uzayında al */ const shX = player.x + player.rarm.x; // player container offsetleri const shY = player.y + player.rarm.y; /* 2) İmlece vektör ve açı (0 rad = sağ) */ const dx = globalX - shX; const dy = globalY - shY; const ang = Math.atan2(dy, dx); /* 3) Kol dönüşü : sprite AŞAĞI baktığı için +90° ( +π/2 ) */ const armRot = ang + Math.PI / 2; player.rarm.rotation = armRot; /* 4) El / silah konumu (kolun tam ucu) ― oyuncu LOKALİNE yazıyoruz */ const L = player.rarm.height; // 110 px player.gun.x = player.rarm.x + Math.sin(armRot) * L; player.gun.y = player.rarm.y - Math.cos(armRot) * L; // ▲ dikkat: -cos /* 5) Silah yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // normalde imleç yönü } }
User prompt
Neden hâlâ “kayık”? Kol sprite’ının pivotu (omuz, anchorY = 0) yukarıda; sprite ise aşağı doğru (Güney) çizilmiş. Dolayısıyla kol ucuna (“el”) ulaşmak için, dönmüş +Y vektörünü kullanmalıyız. Formül şu olmalı: ini Kopyala Düzenle hand.x = shoulder.x − sin(rot) * L hand.y = shoulder.y + cos(rot) * L Senin kodunda cos → x, sin → y yazdığımız için vektör 90° sapmış durumda; silah hep sağ-aşağı kayıyor. Yapman gereken tek değişiklik game.move içindeki pointGunAt fonksiyonunda aşağıdaki iki satırı yerine koy: js Kopyala Düzenle /* 3) El / silah konumu — düzeltildi */ const L = player.rarm.height; // 110 px player.gun.x = sx - Math.sin(armRot) * L; // ← sin NEGATİF player.gun.y = sy + Math.cos(armRot) * L; // ← cos POZİTİF Başka hiçbir satıra dokunma. Aynı formül enemy tarafında da kullanılıyorsa onu da güncelle.
User prompt
Seçenek A – En temiz çözüm Silahın anchor’ını değiştir, kodda yalnızca konum formülü kalsın. js Kopyala Düzenle // Player ve Enemy sınıflarındaki GUN oluşturulurken: var gun = self.attachAsset('playerGun', { anchorX: 0.5, // ortası anchorY: 0, // üst kenar (yukarı bakıyorsa kabza) x: rarm.x, y: rarm.y + rarm.height, rotation: 0 }); Anchor artık kabzanın ortası olduğu için js Kopyala Düzenle player.gun.x = sx + Math.cos(armRot) * L; player.gun.y = sy + Math.sin(armRot) * L; formülü silahı tam kol ucuna getirir. Enemy tarafında da aynı değişikliği yapmayı unutma. 👉 Sprite dosyalarını değiştirmene gerek yok; attachAsset çağrısındaki iki satır yeterli.
User prompt
Eski fonksiyonun yerine “aynen” kopyalaman yeterli; başka satıra dokunma. js Kopyala Düzenle // game.move içindeki yardımcı — GLOBAL koordinat alır function pointGunAt(globalX, globalY) { /* 1) İmleci Player konteynerine çevir */ const p = player.toLocal({ x: globalX, y: globalY }); const sx = player.rarm.x; // omuz (player local) const sy = player.rarm.y; const dx = p.x - sx; const dy = p.y - sy; const ang = Math.atan2(dy, dx); // 0 rad = sağ (doğu) /* 2) Kolun dönüşü Sprite BAŞLANGIÇTA YUKARI bakıyorsa –90° (–π/2) ekle */ const armRot = ang - Math.PI / 2; // /** DEĞİŞTİ **/ player.rarm.rotation = armRot; /* 3) El / silah konumu */ const L = player.rarm.height; // = 110 px player.gun.x = sx + Math.cos(armRot) * L; // /** DEĞİŞTİ **/ player.gun.y = sy + Math.sin(armRot) * L; /* 4) Silah yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // aksi hâlde imleç yönü } }
User prompt
Aşağıdaki pointGunAt fonksiyonunu, mevcut kodundaki aynı isimli fonksiyonun yerine yapıştırman yeterli — başka satıra dokunma: js Kopyala Düzenle // game.move içindeki yardımcı — GLOBAL koordinat alır function pointGunAt(globalX, globalY) { /* 1) İmleci Player konteynerine çevir */ const p = player.toLocal({ x: globalX, y: globalY }); const sx = player.rarm.x; // omuz (player local) const sy = player.rarm.y; const dx = p.x - sx; const dy = p.y - sy; const ang = Math.atan2(dy, dx); // 0 rad = sağ (doğu) /* 2) Kolun gerçek dönüşü ▼ Sprite başlangıçta AŞAĞI baktığı için +90 ° ekliyoruz */ const armRot = ang + Math.PI / 2; player.rarm.rotation = armRot; /* 3) El / silah konumu (sprite’ın alt ucu) */ const L = player.rarm.height; // = 110 px player.gun.x = sx + Math.sin(armRot) * L; player.gun.y = sy + Math.cos(armRot) * L; /* 4) Silah yönü */ if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // aksi hâlde imleç yönü } } Bu fonksiyon, kol sprite’ının “aşağı bakarak” çizildiği varsayımıyla 90 ° düzeltme yapar ve ardından imlece göre döndürür. Kopyalayıp eskisinin yerine koy; başka değişiklik gerekmez.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 0; self.dirX = 0; self.dirY = 0; self.update = function () { self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; }; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); // Body var body = self.attachAsset('enemyBody', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Head var head = self.attachAsset('enemyHead', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -body.height / 2 - 45 }); // Left Arm var larm = self.attachAsset('enemyArm', { anchorX: 0.5, anchorY: 0, x: -body.width / 2 - 10, y: -100 //{t} // 50px up }); // Right Arm (gun hand) var rarm = self.attachAsset('enemyArm', { anchorX: 0.5, anchorY: 0, x: body.width / 2 + 10, y: -100 //{z} // 50px up }); // Legs var lleg = self.attachAsset('enemyLeg', { anchorX: 0.5, anchorY: 0, x: -body.width / 4, y: body.height / 2 - 10 }); var rleg = self.attachAsset('enemyLeg', { anchorX: 0.5, anchorY: 0, x: body.width / 4, y: body.height / 2 - 10 }); // Gun (in hand) var gun = self.attachAsset('enemyGun', { anchorX: 0.5, // 0.5 yerine 0.5 anchorY: 0.5, x: rarm.x, y: rarm.y + rarm.height, rotation: 0 }); // Holster gun (on hip, always visible unless drawn) var hipGun = self.attachAsset('enemyGun', { anchorX: 0.5, anchorY: 0.5, x: body.width / 2 + 8, y: body.height / 2 - 22, rotation: Math.PI / 2 }); // Start with gun in holster, hand empty gun.visible = false; hipGun.visible = true; // Helper methods to switch gun/holster visibility self.toHolster = function () { hipGun.visible = true; gun.visible = false; }; self.toHand = function () { hipGun.visible = false; gun.visible = true; }; self.bodyParts = [body, head, larm, rarm, lleg, rleg, gun]; self.gun = gun; self.rarm = rarm; self.head = head; self.body = body; self.ragdoll = function (hitX, hitY) { for (var i = 0; i < self.bodyParts.length; i++) { var part = self.bodyParts[i]; tween(part, { rotation: (Math.random() - 0.5) * 2.5, x: part.x + (Math.random() - 0.5) * 200, y: part.y + (Math.random() - 0.5) * 200 }, { duration: 600, delay: i * 30, easing: tween.elasticOut }); } }; self.resetPose = function () { body.x = 0; body.y = 0; body.rotation = 0; head.x = 0; head.y = -body.height / 2 - 45; head.rotation = 0; larm.x = -body.width / 2 - 10; larm.y = -100; //{1k} // 50px up larm.rotation = 0; rarm.x = body.width / 2 + 10; rarm.y = -100; //{1n} // 50px up rarm.rotation = 0; lleg.x = -body.width / 4; lleg.y = body.height / 2 - 10; lleg.rotation = 0; rleg.x = body.width / 4; rleg.y = body.height / 2 - 10; rleg.rotation = 0; gun.x = rarm.x; gun.y = rarm.y + rarm.height; gun.rotation = 0; self.toHolster(); // always start with gun in holster }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); // Body var body = self.attachAsset('playerBody', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Head var head = self.attachAsset('playerHead', { anchorX: 0.5, anchorY: 0.5, x: 0, y: -body.height / 2 - 45 }); // Left Arm var larm = self.attachAsset('playerArm', { anchorX: 0.5, anchorY: 0, x: -body.width / 2 - 10, y: -100 //{1S} // 50px up }); // Right Arm (gun hand) var rarm = self.attachAsset('playerArm', { anchorX: 0.5, anchorY: 0, x: body.width / 2 + 10, y: -100 //{1Y} // 50px up }); // Legs var lleg = self.attachAsset('playerLeg', { anchorX: 0.5, anchorY: 0, x: -body.width / 4, y: body.height / 2 - 10 }); var rleg = self.attachAsset('playerLeg', { anchorX: 0.5, anchorY: 0, x: body.width / 4, y: body.height / 2 - 10 }); // Gun (in hand) var gun = self.attachAsset('playerGun', { anchorX: 0.5, // 0.5 yerine 0.5 anchorY: 0.5, x: rarm.x, y: rarm.y + rarm.height, rotation: 0 }); // Holster gun (on hip, always visible unless drawn) var hipGun = self.attachAsset('playerGun', { anchorX: 0.5, anchorY: 0.5, x: body.width / 2 + 8, y: body.height / 2 - 22, rotation: Math.PI / 2 }); // Start with gun in holster, hand empty gun.visible = false; hipGun.visible = true; // Helper methods to switch gun/holster visibility self.toHolster = function () { hipGun.visible = true; gun.visible = false; }; self.toHand = function () { hipGun.visible = false; gun.visible = true; if (typeof holsterVisual !== "undefined" && holsterVisual.parent) { // Remove old kilif and add kilifbos at same position var idx = holsterVisual.parent.getChildIndex ? holsterVisual.parent.getChildIndex(holsterVisual) : -1; var parent = holsterVisual.parent; var oldX = holsterVisual.x; var oldY = holsterVisual.y; parent.removeChild(holsterVisual); holsterVisual = LK.getAsset('kilifbos', { width: 270, height: 270, anchorX: -0.2, anchorY: 0 }); // Spawn kilifbos 20 pixels right of kilif asset's spawnpoint holsterVisual.x = oldX + 20; holsterVisual.y = oldY; if (idx >= 0 && parent.addChildAt) { parent.addChildAt(holsterVisual, idx); } else { parent.addChild(holsterVisual); } } }; // Used for ragdoll effect self.bodyParts = [body, head, larm, rarm, lleg, rleg, gun]; // Used for aiming self.gun = gun; self.rarm = rarm; // Used for hit detection self.head = head; self.body = body; // Used for ragdoll self.ragdoll = function (hitX, hitY) { // Animate all parts to random positions/rotations for (var i = 0; i < self.bodyParts.length; i++) { var part = self.bodyParts[i]; tween(part, { rotation: (Math.random() - 0.5) * 2.5, x: part.x + (Math.random() - 0.5) * 200, y: part.y + (Math.random() - 0.5) * 200 }, { duration: 600, delay: i * 30, easing: tween.elasticOut }); } }; // Reset pose self.resetPose = function () { body.x = 0; body.y = 0; body.rotation = 0; head.x = 0; head.y = -body.height / 2 - 45; head.rotation = 0; larm.x = -body.width / 2 - 10; larm.y = -100; //{2J} // 50px up larm.rotation = 0; rarm.x = body.width / 2 + 10; rarm.y = -100; //{2M} // 50px up rarm.rotation = 0; lleg.x = -body.width / 4; lleg.y = body.height / 2 - 10; lleg.rotation = 0; rleg.x = body.width / 4; rleg.y = body.height / 2 - 10; rleg.rotation = 0; gun.x = rarm.x; gun.y = rarm.y + rarm.height; gun.rotation = 0; self.toHolster(); // always start with gun in holster }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2e1a09 }); /**** * Game Code ****/ // Player and enemy bodies (torso, head, arms, legs) as simple shapes // Game state var STATE_WAIT = 0; var STATE_DRAW = 1; var STATE_SHOT = 2; var STATE_RESULT = 3; var duelState = STATE_WAIT; var canShoot = false; var playerShot = false; var enemyShot = false; var playerBullet = null; var enemyBullet = null; var duelTimer = null; var drawTimeout = null; var resultTimeout = null; var duelStartTime = 0; var playerShotTime = 0; var enemyShotTime = 0; var aimX = 0; var aimY = 0; var aimRadius = 180; var aimAngle = 0; var aimSpeed = 0.018; // %30 daha yavaş var aimDir = 1; var aimActive = false; var playerScore = 0; var roundNum = 1; var maxRounds = 5; // === GLOBAL SHOT COUNTERS === var playerShotsFiredCnt = 0; var enemyShotsFiredCnt = 0; var enemyData = [{ name: "Greenhorn", minReact: 3.0, maxReact: 3.4, coneStart: 42, coneEnd: 0 }, { name: "Billy the Kid", minReact: 2.4, maxReact: 2.7, coneStart: 36, coneEnd: 0 }, { name: "Doc Holliday", minReact: 1.6, maxReact: 1.9, coneStart: 30, coneEnd: 0 }, { name: "Calamity Jane", minReact: 1.0, maxReact: 1.3, coneStart: 24, coneEnd: 0 }, { name: "The Undertaker", minReact: 0.6, maxReact: 0.8, coneStart: 18, coneEnd: 0, scale: 1.5 }]; var currentEnemy = null; // ==== FIX #1 : SAHNENİN BAŞINDA ==== var world = new Container(); game.addChild(world); // Player and enemy var player = new Player(); var enemy = new Enemy(); world.addChild(player); world.addChild(enemy); // Center positions var centerX = 2048 / 2; var playerY = 2732 * 0.7; var enemyY = 2732 * 0.3; // 6-bullet UI for player and enemy var playerAmmoUI = []; var enemyAmmoUI = []; function setupAmmoUI() { // Remove old UI if any for (var i = 0; i < playerAmmoUI.length; i++) { if (playerAmmoUI[i].parent) { playerAmmoUI[i].parent.removeChild(playerAmmoUI[i]); } } for (var i = 0; i < enemyAmmoUI.length; i++) { if (enemyAmmoUI[i].parent) { enemyAmmoUI[i].parent.removeChild(enemyAmmoUI[i]); } } playerAmmoUI = []; enemyAmmoUI = []; for (var i = 0; i < 6; i++) { var px = player.x - 120 + i * 40; var ex = enemy.x - 120 + i * 40; var bulletP = LK.getAsset('bullet', { scaleX: 0.6, scaleY: 0.6, anchorX: 0.5, anchorY: 0.5 }); var bulletE = LK.getAsset('bullet', { scaleX: 0.6, scaleY: 0.6, anchorX: 0.5, anchorY: 0.5 }); bulletP.y = player.y + 250 + 60; // Düşman: yalnızca 5. raundda 75 px yukarı var enemyExtraY = roundNum === 5 ? -75 : 0; bulletE.y = enemy.y - 250 + enemyExtraY; bulletP.x = px; bulletE.x = ex; // HUD’u world içine koy ki zoom animasyonuyla birlikte büyüsün world.addChild(bulletP); world.addChild(bulletE); playerAmmoUI.push(bulletP); enemyAmmoUI.push(bulletE); } } // Position player and enemy player.x = centerX - 500; player.y = playerY; enemy.x = centerX + 500; enemy.y = enemyY; // Score text var scoreTxt = new Text2('Score: 0', { size: 90, fill: 0xFFF7D6 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Round text var roundTxt = new Text2('', { size: 70, fill: 0xFFE4B5 }); roundTxt.anchor.set(0.5, 0); LK.gui.top.addChild(roundTxt); roundTxt.y = 110; // Duel status text var statusTxt = new Text2('', { size: 110, fill: 0xFFECB3 }); statusTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(statusTxt); // Aim reticle var aimReticle = LK.getAsset('bullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5, tint: 0xff0000 }); aimReticle.visible = false; game.addChild(aimReticle); // Helper: reset all state for a new round function resetDuel() { duelState = STATE_WAIT; canShoot = false; playerShot = false; enemyShot = false; playerBullet = null; enemyBullet = null; duelStartTime = 0; playerShotTime = 0; enemyShotTime = 0; aimAngle = Math.random() * Math.PI * 2; aimDir = Math.random() > 0.5 ? 1 : -1; aimActive = false; aimReticle.visible = false; player.resetPose(); enemy.resetPose(); player.toHolster(); enemy.toHolster(); if (typeof holsterVisual !== "undefined" && holsterVisual.parent) { var idx = holsterVisual.parent.getChildIndex ? holsterVisual.parent.getChildIndex(holsterVisual) : -1; var parent = holsterVisual.parent; var oldX = holsterVisual.x; var oldY = holsterVisual.y; parent.removeChild(holsterVisual); holsterVisual = LK.getAsset('kilif', { width: 300, height: 300, anchorX: -0.2, anchorY: 0 }); holsterVisual.x = oldX; holsterVisual.y = oldY; if (idx >= 0 && parent.addChildAt) { parent.addChildAt(holsterVisual, idx); } else { parent.addChild(holsterVisual); } } setupAmmoUI(); // === RESET SHOT COUNTERS === playerShotsFiredCnt = 0; enemyShotsFiredCnt = 0; // === RESET HOLSTER FLAGS === playerReady = false; // yeni ← round’a nötr gir holdingHolster = false; // yeni holsterHoldTime = 0; // güvenlik duelStarted = false; // <-- YENİ: her raunda nötr gir cancelHold(); // 1. raunddan kalma musicTimeout varsa temizle zoomFinished = false; // yeni animasyona hazırlan var roundMusic = roundNum === 1 ? 'duelmusic' : roundNum === 2 ? 'round2music' : roundNum === 3 ? 'round3music' : roundNum === 4 ? 'round4music' : 'round5music'; startZoomIn(roundMusic); statusTxt.setText("Wait for the music..."); statusTxt.visible = true; // Set up enemy for this round currentEnemy = enemyData[roundNum - 1]; roundTxt.setText("Round " + roundNum + ": " + currentEnemy.name); // Boss scale (if any) enemy.scaleX = enemy.scaleY = currentEnemy.scale || 1; // Play duel music // (music now only plays during zoom-in, do not play here) // drawTimeout is now set after zoom-in, not here if (drawTimeout) { LK.clearTimeout(drawTimeout); } } // Start the "DRAW!" phase function startDraw() { if (!playerReady) { earlyLose(); return; } duelState = STATE_DRAW; canShoot = true; aimActive = true; aimReticle.visible = true; statusTxt.setText("DRAW!"); statusTxt.visible = true; LK.stopMusic(); LK.getSound('draw').play(); player.toHand(); // draw from holster enemy.toHand(); // enemy draws too aimEnemyGunAt(player.x, player.y - 40); // hemen hizala duelStartTime = Date.now(); // Enemy will shoot after their reaction time var reactTime = 1200; // fallback default if (currentEnemy && typeof currentEnemy.minReact === "number" && typeof currentEnemy.maxReact === "number") { reactTime = 1000 * (currentEnemy.minReact + Math.random() * (currentEnemy.maxReact - currentEnemy.minReact)); reactTime *= 0.425; // %57.5 daha hızlı tepki (eski 0.5 ve yeni 0.35 arası) } if (duelTimer) { LK.clearTimeout(duelTimer); } duelTimer = LK.setTimeout(enemyFire, reactTime); } // Player fires function playerFire(x, y) { // 6 mermi limiti if (playerShotsFiredCnt >= 6) { statusTxt.setText("Out of ammo!"); statusTxt.visible = true; return; } if (!canShoot) { return; } // playerShot kısıtlamasını kaldır playerShot = true; playerShotsFiredCnt++; // sayaç ↑ playerShotTime = Date.now(); // Animate gun tween(player.gun, { rotation: -0.5 }, { duration: 80, easing: tween.cubicOut }); tween(player.rarm, { rotation: -0.3 }, { duration: 80, easing: tween.cubicOut }); LK.getSound('gunshot').play(); // Create bullet playerBullet = new Bullet(); // Muzzle position helper function muzzlePos() { // Use full gun width/height for muzzle (center anchor) var gunW = player.gun.width || 60; var gunH = player.gun.height || 15; return { x: player.x + player.gun.x + Math.cos(player.gun.rotation) * gunW, y: player.y + player.gun.y + Math.sin(player.gun.rotation) * gunH }; } var muzzle = muzzlePos(); playerBullet.x = muzzle.x; playerBullet.y = muzzle.y; // Ateş anındaki imleç (x, y) fonksiyona zaten parametre olarak geliyor var dx = x - muzzle.x; var dy = y - muzzle.y; var dist = Math.sqrt(dx * dx + dy * dy); playerBullet.dirX = dx / dist; playerBullet.dirY = dy / dist; playerBullet.speed = 60; game.addChild(playerBullet); // Decrement player bullet UI for (var i = 0; i < playerAmmoUI.length; i++) { if (playerAmmoUI[i].visible !== false) { playerAmmoUI[i].visible = false; break; } } // If shot before draw, instant loss if (duelState === STATE_WAIT) { duelState = STATE_RESULT; statusTxt.setText("You shot too early!\nYou Lose!"); statusTxt.visible = true; LK.getSound('fail').play(); player.ragdoll(); enemy.ragdoll(); endRound(false); return; } // bir sonraki mermiye izin ver if (duelState === STATE_DRAW && playerShotsFiredCnt < 6) { canShoot = true; aimActive = true; aimReticle.visible = true; } // DRAW fazı açık kalsın ki 6 mermi bitene kadar tekrar tekrar ateş edebilelim } // Enemy fires function enemyFire() { var _currentEnemy; if (enemyShotsFiredCnt >= 6 || duelState === STATE_RESULT) { return; } if (!enemyShot) { enemyShot = true; } // ilk mermi için eski bayrak enemyShotsFiredCnt++; enemyShotTime = Date.now(); // Ateşten önce hedefe çevir aimEnemyGunAt(player.x, player.y - 40); // Animate gun tween(enemy.gun, { rotation: 0.5 }, { duration: 80, easing: tween.cubicOut }); tween(enemy.rarm, { rotation: 0.3 }, { duration: 80, easing: tween.cubicOut }); LK.getSound('gunshot').play(); // Create bullet enemyBullet = new Bullet(); var gunW = enemy.gun.width || 60; var gunH = enemy.gun.height || 18; enemyBullet.x = enemy.x + enemy.gun.x + Math.cos(enemy.gun.rotation) * gunW; enemyBullet.y = enemy.y + enemy.gun.y + Math.sin(enemy.gun.rotation) * gunH; // Decrement enemy bullet UI for (var i = 0; i < enemyAmmoUI.length; i++) { if (enemyAmmoUI[i].visible !== false) { enemyAmmoUI[i].visible = false; break; } } // Konik isabet modeliyle hedef seçimi // 1️⃣ hedef vektörü var baseDX = player.x - enemyBullet.x; var baseDY = player.y - 40 - enemyBullet.y; // gövdenin biraz üstü var baseAng = Math.atan2(baseDY, baseDX); // 2️⃣ saçılma açısı (daralan koni) var sIdx = enemyShotsFiredCnt; // 1-6 var sMax = 6; var cStart = currentEnemy && typeof currentEnemy.coneStart === "number" ? currentEnemy.coneStart : 24; // fallback var cEnd = currentEnemy && typeof currentEnemy.coneEnd === "number" ? currentEnemy.coneEnd : 0; var coneDeg = cStart + (cEnd - cStart) * ((sIdx - 1) / (sMax - 1)); var coneRad = coneDeg * Math.PI / 180; var isLast = sIdx === sMax; // son kurşun var spread = isLast ? 0 : Math.random() * coneRad - coneRad / 2; // 3️⃣ hedef noktasını diagramdaki yayı keserek bul var range = 1500; // ekran dışına yeter var targetX = enemyBullet.x + Math.cos(baseAng + spread) * range; var targetY = enemyBullet.y + Math.sin(baseAng + spread) * range; var dx = targetX - enemyBullet.x; var dy = targetY - enemyBullet.y; var dist = Math.sqrt(dx * dx + dy * dy); enemyBullet.dirX = dx / dist; enemyBullet.dirY = dy / dist; enemyBullet.speed = 60; game.addChild(enemyBullet); // sonraki mermi (tak-tak) 0.6 sn sonra if (enemyShotsFiredCnt < 6) { LK.setTimeout(enemyFire, 600); } // Round oyuncu ateş etmediyse ANCAK bütün 6 mermi atıldıktan sonra if (enemyShotsFiredCnt === 6 && !playerShot) { // Son kurşunun ekrandan çıkması için çok kısa bir gecikme bırak LK.setTimeout(function () { if (duelState !== STATE_RESULT) { duelState = STATE_RESULT; statusTxt.setText("You Survived!"); statusTxt.visible = true; endRound(true); } }, 350); } } // End round, win: true/false function endRound(win) { canShoot = false; aimActive = false; aimReticle.visible = false; if (drawTimeout) { LK.clearTimeout(drawTimeout); } if (duelTimer) { LK.clearTimeout(duelTimer); } if (resultTimeout) { LK.clearTimeout(resultTimeout); } drawTimeout = null; duelTimer = null; resultTimeout = null; // Next round or end game resultTimeout = LK.setTimeout(function () { if (win) { playerScore += 1; scoreTxt.setText("Score: " + playerScore); roundNum += 1; if (roundNum > maxRounds) { statusTxt.setText("You Win!\nScore: " + playerScore); statusTxt.visible = true; LK.showYouWin(); } else { resetDuel(); } } else { statusTxt.setText("You Lose!\nScore: " + playerScore); statusTxt.visible = true; LK.showGameOver(); } }, 1600); } // Handle aiming reticle movement (circular motion) function updateAimReticle() { if (!aimActive) { return; } aimAngle += aimSpeed * aimDir; var r = aimRadius; var ex = enemy.x; var ey = enemy.y; // Reticle orbits enemy's body aimReticle.x = ex + Math.cos(aimAngle) * r; aimReticle.y = ey + Math.sin(aimAngle) * r * 0.7; } // Handle bullet collisions and duel result function checkBullets() { // Player bullet hits enemy if (playerBullet) { // Check if bullet reached enemy var dx = playerBullet.x - enemy.x; var dy = playerBullet.y - enemy.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 120) { // Hit! LK.getSound('hit').play(); enemy.ragdoll(playerBullet.x, playerBullet.y); game.removeChild(playerBullet); playerBullet = null; duelState = STATE_RESULT; statusTxt.setText("You Win the Duel!"); statusTxt.visible = true; endRound(true); } } // Enemy bullet hits player if (enemyBullet) { var dx = enemyBullet.x - player.x; var dy = enemyBullet.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < 120) { LK.getSound('hit').play(); player.ragdoll(enemyBullet.x, enemyBullet.y); game.removeChild(enemyBullet); enemyBullet = null; duelState = STATE_RESULT; statusTxt.setText("You were shot!"); statusTxt.visible = true; endRound(false); } } // Both bullets exist (simultaneous fire) if (playerBullet && enemyBullet) { // Check which bullet hits first var pdx = playerBullet.x - enemy.x; var pdy = playerBullet.y - enemy.y; var pdist = Math.sqrt(pdx * pdx + pdy * pdy); var edx = enemyBullet.x - player.x; var edy = enemyBullet.y - player.y; var edist = Math.sqrt(edx * edx + edy * edy); if (pdist < 120 && edist < 120) { // Both hit at same time: draw LK.getSound('hit').play(); player.ragdoll(); enemy.ragdoll(); game.removeChild(playerBullet); game.removeChild(enemyBullet); playerBullet = null; enemyBullet = null; duelState = STATE_RESULT; statusTxt.setText("Draw!\nBoth shot!"); statusTxt.visible = true; endRound(false); } else if (pdist < 120) { LK.getSound('hit').play(); enemy.ragdoll(playerBullet.x, playerBullet.y); game.removeChild(playerBullet); playerBullet = null; duelState = STATE_RESULT; statusTxt.setText("You Win the Duel!"); statusTxt.visible = true; endRound(true); } else if (edist < 120) { LK.getSound('hit').play(); player.ragdoll(enemyBullet.x, enemyBullet.y); game.removeChild(enemyBullet); enemyBullet = null; duelState = STATE_RESULT; statusTxt.setText("You were shot!"); statusTxt.visible = true; endRound(false); } } // Remove bullets if off screen if (playerBullet && (playerBullet.x < 0 || playerBullet.x > 2048 || playerBullet.y < 0 || playerBullet.y > 2732)) { game.removeChild(playerBullet); playerBullet = null; canShoot = true; // anında yeni atış serbest } if (enemyBullet && (enemyBullet.x < 0 || enemyBullet.x > 2048 || enemyBullet.y < 0 || enemyBullet.y > 2732)) { game.removeChild(enemyBullet); enemyBullet = null; enemyShot = false; // yeni atışa izin ver } } // ==== FIX #2 : holster konumu ==== var holsterOffset = 250; var holsterBox = new Rectangle(player.x - 200, player.y + player.body.height / 2 + holsterOffset, 400, 200); // Show holster box as a kilif image var holsterVisual = LK.getAsset('kilif', { width: 300, height: 300, anchorX: -0.2, anchorY: 0 }); holsterVisual.x = holsterBox.x; holsterVisual.y = holsterBox.y; world.addChild(holsterVisual); // Holster hold/zoom/duel state var zoomFinished = false, duelStarted = false, holsterHoldTime = 0; var playerReady = false; var holdingHolster = false; // Track if holster is being held var musicTimeout = null; // Timer for music/draw phase function beginHold() { if (musicTimeout) { LK.clearTimeout(musicTimeout); } var extra = 4000 + Math.random() * 6000; // 4-10 s musicTimeout = LK.setTimeout(stopMusicAndDraw, extra); } function cancelHold() { if (musicTimeout) { LK.clearTimeout(musicTimeout); } musicTimeout = null; } function stopMusicAndDraw() { LK.stopMusic(); // müzik sustu duelStarted = true; // <-- ERKEN KAYIP KONTROLÜ ARTIK PASİF holsterHoldTime = 0; // güvenlik: sayaç sıfırla startDraw(); // DRAW fazına geç } // Touch/click to fire or start holster hold game.down = function (x, y, obj) { // No fire until duel actually started if (zoomFinished && !duelStarted && holsterBox.contains(x, y)) { playerReady = true; holdingHolster = true; // holster pressed player.toHand(); // ← kılıftan çek (hemen ele ver) pointGunAt(x, y); // artık global ve erişilebilir beginHold(); // HOLD başlatılırken zamanlayıcı kuruluyor return; } if (!duelStarted) { return; } if (duelState === STATE_DRAW && canShoot && aimActive) { playerFire(x, y); } else if (duelState === STATE_WAIT && !playerShot) { playerFire(x, y); } }; // On pointer up, check for early leave from holster // ==== FIX #4c : tetikleyici ===== game.up = function (x, y, obj) { // HOLSTER EARLY RELEASE CHECK holdingHolster = false; // holster released cancelHold(); // el çekildi, zamanlayıcı iptal if (!duelStarted && playerReady && duelState === STATE_WAIT) { earlyLose(); return; } if (duelState === STATE_DRAW && canShoot) { playerFire(x, y); return; } }; // Move reticle with finger (optional: drag to aim) game.move = function (x, y, obj) { // Holster hold/early leave logic if (zoomFinished && !duelStarted) { if (holsterBox.contains(x, y)) { // handled in update for dt-accurate timing } else if (holdingHolster) { cancelHold(); earlyLose(); } } if (aimActive) { // Clamp reticle to a circle around enemy var ex = enemy.x; var ey = enemy.y; var dx = x - ex; var dy = y - ey; var d = Math.sqrt(dx * dx + dy * dy); if (d > aimRadius) { dx = dx * (aimRadius / d); dy = dy * (aimRadius / d); } aimReticle.x = ex + dx; aimReticle.y = ey + dy; // Update angle for next frame aimAngle = Math.atan2(aimReticle.y - ey, aimReticle.x - ex); } // Namlu her zaman fareyi izlesin (DRAW’tan önce holster tutulurken de) pointGunAt(x, y); }; /**** GLOBAL YARDIMCI : Silahı imlece çevir ****/ function pointGunAt(globalX, globalY) { // 1) Omuz pivotu – dünya koordinatı var shX = player.x + player.rarm.x; var shY = player.y + player.rarm.y; // 2) Omuz → imleç vektörü ve açı (0 rad = sağ) var dx = globalX - shX; var dy = globalY - shY; var ang = Math.atan2(dy, dx); // 3) Kol sprite’ı AŞAĞI bakıyor → –90° (-π/2) düzelt var armRot = ang - Math.PI / 2; player.rarm.rotation = armRot; // 4) El / silah konumu (player LOCAL) var L = player.rarm.height; // ≈110 px // ❗️ Doğru ofset: (-sin, +cos) player.gun.x = player.rarm.x - Math.sin(armRot) * L; player.gun.y = player.rarm.y + Math.cos(armRot) * L; // 5) Silah namlu yönü if (!duelStarted && holsterBox.contains(globalX, globalY)) { player.gun.rotation = Math.PI / 2; // kılıfta ⇒ namlu yere } else { player.gun.rotation = ang; // hedefe bak } } /**** GLOBAL : Enemy silahını hedefe çevir ****/ function aimEnemyGunAt(globalX, globalY) { // 1) Omuz pivotu (world) var shX = enemy.x + enemy.rarm.x; var shY = enemy.y + enemy.rarm.y; // 2) Omuz→hedef vektörü var dx = globalX - shX; var dy = globalY - shY; var ang = Math.atan2(dy, dx); // 3) Kol sprite’ı AŞAĞI bakıyor → –90° (–π/2) düzeltme var armRot = ang - Math.PI / 2; enemy.rarm.rotation = armRot; // 4) El / silah konumu (enemy LOCAL) **ayna!** var L = enemy.rarm.height; // ≈145 px enemy.gun.x = enemy.rarm.x - Math.sin(armRot) * L; enemy.gun.y = enemy.rarm.y + Math.cos(armRot) * L; // 5) Namluyu hedefe döndür enemy.gun.rotation = ang; } // Helper to update holster box position under player's feet function updateHolsterBox() { holsterBox.x = player.x - 200; holsterBox.y = player.y + player.body.height / 2 + holsterOffset; holsterVisual.x = holsterBox.x; holsterVisual.y = holsterBox.y; } // Main update loop game.update = function (dt) { // Hide status text during zoom-in if (!zoomFinished) { statusTxt.visible = false; return; } // Always update holster position to follow player updateHolsterBox(); // Animate aim reticle updateAimReticle(); // Rakip silahı eldeyse oyuncuyu takip etsin if (enemy.gun.visible) { aimEnemyGunAt(player.x, player.y - 40); } // Animate bullets if (playerBullet) { playerBullet.update(); } if (enemyBullet) { enemyBullet.update(); } // Check for bullet collisions checkBullets(); // ==== FIX #3 : statusTxt ayarı ==== // Holster hold logic after zoom if (zoomFinished && !duelStarted) { // Use pointerX/Y for current pointer var px = typeof game.pointerX === "number" ? game.pointerX : 0; var py = typeof game.pointerY === "number" ? game.pointerY : 0; var dtMs = typeof dt === "number" ? dt : 16.7; if (holsterBox.contains(px, py) && holdingHolster) { holsterHoldTime += dtMs; } else { if (holsterHoldTime > 0 && holdingHolster) { earlyLose(); } holsterHoldTime = 0; } if (!duelStarted) { if (!playerReady) { statusTxt.setText("Hold holster to start duel"); } else { statusTxt.setText("Wait for music to end…\nthen aim & release"); } } // if (holsterHoldTime >= 4000 && !duelStarted) { // duelStarted = true; // holsterHoldTime = 0; // resetDuel(); // } statusTxt.visible = true; } else { if (duelState === STATE_DRAW) { statusTxt.setText("Aim and SHOOT!"); } statusTxt.visible = true; } }; // Early lose function function earlyLose() { if (duelState === STATE_RESULT) { return; } // only trigger once holdingHolster = false; holsterHoldTime = 0; duelStarted = false; LK.stopMusic(); if (drawTimeout) { LK.clearTimeout(drawTimeout); } statusTxt.setText("Too early!\nYou lose!"); statusTxt.visible = true; LK.getSound('gunshot').play(); // yere ateş LK.getSound('fail').play(); // Optionally, also play gunshot sound: // LK.getSound('gunshot').play(); // Show game over after 1 second LK.setTimeout(function () { LK.showGameOver(); }, 1000); } // Camera zoom-in before duel starts function startZoomIn(music) { // ==== FIX #1b : zoom fonksiyonunda ==== var startScale = 0.4; world.scaleX = world.scaleY = startScale; world.x = centerX * (1 - startScale); world.y = 2732 / 2 * (1 - startScale); LK.playMusic(music || 'duelmusic'); tween(world, { scaleX: 1, scaleY: 1, x: 0, y: 0 }, { duration: 4000, easing: tween.quadInOut, onFinish: function onFinish() { zoomFinished = true; } }); } // Start zoom-in and music immediately on boot startZoomIn();
===================================================================
--- original.js
+++ change.js
@@ -224,9 +224,10 @@
height: 270,
anchorX: -0.2,
anchorY: 0
});
- holsterVisual.x = oldX;
+ // Spawn kilifbos 20 pixels right of kilif asset's spawnpoint
+ holsterVisual.x = oldX + 20;
holsterVisual.y = oldY;
if (idx >= 0 && parent.addChildAt) {
parent.addChildAt(holsterVisual, idx);
} else {