User prompt
Oyuncuların kafasının üzerinde resimler var. Onları kaldır. Onların yerine can health bar'ı ekle ve o beşer tane canları olsun.
User prompt
Oyuncuların kafalarının üstündeki barlar için bir aset aç ve onlara yeni resim ekleyebileyim.
User prompt
başlasın. Dövüşçüler birbirinden uzakta başlasın dövüşe.
User prompt
Cam barlarını arka plan resminin üst kısmına büyük olarak ekle ve her bir oyuncunun 10 tane canı olsun.
User prompt
Sağdakine bir bot oynasın. Aynı anda iki kişi oynadığında ise onlar karşılıklı yüzleşsin.
User prompt
Oyunculara can barı ekler misin? Bir de oyuncuların can barı bizim görebileceğimiz şekilde olsun ve oyuncular birbirine yaklaşıp dövüşebilsinler.
User prompt
jump
User prompt
Cam barını büyütelim her iki oyuncuda da ve biraz daha oyuncular birbirine yaklaşarak vuruşsunlar. Vurduklarında sesler çıksın.
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'length')' in or related to this line: 'self.body = self.attachAsset(self.assetId, {' Line Number: 28
Code edit (1 edits merged)
Please save this source code
User prompt
Dragon Arena: Çin Dövüşü
Initial prompt
bir dövüş oyunu istiyorum arkası çin temalı olacak ve dövüşe başlarken Fight yazsın istiyorum.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Dövüşçü sınıfı var Fighter = Container.expand(function (assetId) { var self = Container.call(this); // Özellikler self.hp = 100; self.isAttacking = false; self.isDefending = false; self.isPlayer = false; // Oyuncu mu, rakip mi self.attackCooldown = 0; self.defendCooldown = 0; self.assetId = assetId || 'fighter1'; // default to 'fighter1' if not provided // Görsel self.body = self.attachAsset(self.assetId, { anchorX: 0.5, anchorY: 1, dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 12, dropShadowAngle: Math.PI / 2, dropShadowBlur: 16, dropShadowAlpha: 0.7 }); // Headbars are now managed globally, not above fighters' heads self.hearts = []; // Saldırı animasyonu self.attackAnim = function () { if (self.isAttacking || self.attackCooldown > 0) return; self.isAttacking = true; self.attackCooldown = 30; // 0.5 sn var oldX = self.x; var targetX = self.x + (self.isPlayer ? 80 : -80); tween(self, { x: targetX }, { duration: 120, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { x: oldX }, { duration: 120, easing: tween.cubicIn, onFinish: function onFinish() { self.isAttacking = false; } }); } }); }; // Savunma animasyonu self.defendAnim = function () { if (self.isDefending || self.defendCooldown > 0) return; self.isDefending = true; self.defendCooldown = 40; // 0.66 sn tween(self.body, { scaleX: 1.2, scaleY: 0.8 }, { duration: 100, easing: tween.easeIn, onFinish: function onFinish() { tween(self.body, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { self.isDefending = false; } }); } }); }; // Hasar alma self.takeHit = function (amount) { if (self.isDefending) { amount = Math.floor(amount / 2); } self.hp -= amount; if (self.hp < 0) self.hp = 0; self.updateHpBar(); // Kırmızıya flash ve titreme efekti LK.effects.flashObject(self.body, 0xff0000, 120); // Titreme efekti: X ekseninde hızlıca ileri geri hareket var originalX = self.x; // Geriye doğru bir adım kaçma animasyonu (hasar alınan yöne göre) // Oyuncu ise sola, rakip ise sağa kaçar // Bot (fighter2) için: aldığı toplam hasara göre knockback mesafesini artır var knockbackDist; if (self.isPlayer) { knockbackDist = -60; } else { // Bot için: hasar aldıkça daha fazla geri kaçar // 100 can: 60px, 80 can: 80px, 60 can: 100px, 40 can: 120px, 20 can: 140px, 0 can: 160px var base = 60; var extra = Math.floor((100 - self.hp) / 20) * 20; // 0, 20, 40, 60, 80 knockbackDist = base + extra; } tween(self, { x: originalX + knockbackDist }, { duration: 90, easing: tween.cubicOut, onFinish: function onFinish() { // Titreme efekti: X ekseninde hızlıca ileri geri hareket tween(self, { x: originalX - 18 }, { duration: 40, easing: tween.linear, onFinish: function onFinish() { tween(self, { x: originalX + 18 }, { duration: 40, easing: tween.linear, onFinish: function onFinish() { tween(self, { x: originalX }, { duration: 40, easing: tween.linear }); } }); } }); } }); // Vuruş sesi: oyuncu ve rakip için farklı sesler if (self.assetId === 'fighter1') { LK.getSound('hit1').play(); } else { LK.getSound('hit2').play(); } }; // Can barını güncelle self.updateHpBar = function () { // 5 cana böl, kalan cana göre kalpleri göster/gizle var heartsToShow = Math.ceil(self.hp / 20); if (self.isPlayer) { for (var i = 0; i < 5; i++) { if (typeof headbars1 !== "undefined" && headbars1[i]) { headbars1[i].alpha = i < heartsToShow ? 1 : 0.2; } } } else { for (var i = 0; i < 5; i++) { if (typeof headbars2 !== "undefined" && headbars2[i]) { headbars2[i].alpha = i < heartsToShow ? 1 : 0.2; } } } }; // Zıplama animasyonu ve durumu self.isJumping = false; self.jumpVy = 0; self.jumpBaseY = 0; self.jumpAnim = function () { if (self.isJumping || self.isAttacking || self.isDefending) return; self.isJumping = true; self.jumpVy = -38; // ilk yukarı hız self.jumpBaseY = self.y; self.jumpHoldTimer = 0; // 2 saniye havada kalma sayacı self.jumpState = "up"; // "up", "hold", "down" }; self.update = function () { if (self.attackCooldown > 0) self.attackCooldown--; if (self.defendCooldown > 0) self.defendCooldown--; // Zıplama güncellemesi if (self.isJumping) { if (self.jumpState === "up") { self.y += self.jumpVy; self.jumpVy += 4; // yerçekimi if (self.jumpVy >= 0) { // Tepeye ulaştı, 0.5 saniye havada kal self.jumpState = "hold"; self.jumpHoldTimer = 30; // 0.5 saniye (60 FPS * 0.5) self.jumpVy = 0; } } else if (self.jumpState === "hold") { self.jumpHoldTimer--; // Havada sabit kal if (self.jumpHoldTimer <= 0) { self.jumpState = "down"; self.jumpVy = 4; // Aşağıya düşmeye başla } } else if (self.jumpState === "down") { self.y += self.jumpVy; self.jumpVy += 4; // yerçekimi if (self.y >= self.jumpBaseY) { self.y = self.jumpBaseY; self.isJumping = false; self.jumpVy = 0; self.jumpState = undefined; self.jumpHoldTimer = 0; } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ // Bot için ayrı headbar asset // Dövüşçü 1: Kırmızı kutu, Dövüşçü 2: Mavi kutu, Arenanın zemini: Geniş sarı kutu, "Fight" için: büyük metin // Arena zemini ve dekor var arenaFloor = LK.getAsset('arenaFloor', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2050 }); game.addChild(arenaFloor); // Ejderha dekorları (üstte ve altta) var dragonTop = LK.getAsset('dragonDeco', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 80 }); var dragonBottom = LK.getAsset('dragonDeco', { anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: 2732 - 80 }); game.addChild(dragonTop); game.addChild(dragonBottom); // Dövüşçüler var fighter1 = new Fighter('fighter1'); fighter1.isPlayer = true; fighter1.scaleX = 1.25; fighter1.scaleY = 1.25; // Oyuncuları birbirinden uzakta başlat fighter1.x = 2048 / 2 - 400; fighter1.y = 2050; game.addChild(fighter1); var fighter2 = new Fighter('fighter2'); fighter2.isPlayer = false; fighter2.scaleX = 1.25; fighter2.scaleY = 1.25; fighter2.x = 2048 / 2 + 400; fighter2.y = 2050; game.addChild(fighter2); // Oyuncuyu öne getir (en üstte çizilsin) game.addChild(fighter1); // assetId'yi constructor parametresi olarak verelim ve Fighter class'ında kullanalım // Headbars (health bars) at top left and top right var headbars1 = []; var headbars2 = []; for (var i = 0; i < 5; i++) { var heart1 = LK.getAsset('headBar', { width: 110, height: 110, color: 0xef4244, anchorX: 0.5, anchorY: 0, // Move even more inward (from 140 to 200), more spacing (from 90 to 110), and further down (from 120 to 180) x: 200 + i * 110, y: 120, dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 8, dropShadowAngle: Math.PI / 2, dropShadowBlur: 12, dropShadowAlpha: 0.7 }); game.addChild(heart1); headbars1.push(heart1); var heart2 = LK.getAsset('headBarBot', { width: 110, height: 110, color: 0x3a8cff, anchorX: 0.5, anchorY: 0, // Move even more inward (from 140 to 200), more spacing (from 90 to 110), and further down (from 120 to 180) x: 2048 - 200 - (4 - i) * 110, y: 120, dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 8, dropShadowAngle: Math.PI / 2, dropShadowBlur: 12, dropShadowAlpha: 0.7 }); game.addChild(heart2); headbars2.push(heart2); } // Round ve intro yazılarını yönetmek için yardımcı fonksiyonlar var roundIntroText = null; var fightText = null; var roundIntroTimeouts = []; function clearRoundIntroTimeouts() { for (var i = 0; i < roundIntroTimeouts.length; i++) { LK.clearTimeout(roundIntroTimeouts[i]); } roundIntroTimeouts = []; } function showRoundIntro(roundNum, _onFinish) { clearRoundIntroTimeouts(); // Dövüşçüleri round başı pozisyonlarına döndür if (typeof fighter1 !== "undefined" && typeof fighter2 !== "undefined") { fighter1.x = 2048 / 2 - 400; fighter1.y = 2050; fighter1.scaleX = 1.25; fighter1.scaleY = 1.25; fighter2.x = 2048 / 2 + 400; fighter2.y = 2050; fighter2.scaleX = 1.25; fighter2.scaleY = 1.25; // Saldırı/savunma/jump state sıfırla fighter1.isAttacking = false; fighter1.isDefending = false; fighter1.isJumping = false; fighter1.attackCooldown = 0; fighter1.defendCooldown = 0; fighter2.isAttacking = false; fighter2.isDefending = false; fighter2.isJumping = false; fighter2.attackCooldown = 0; fighter2.defendCooldown = 0; fighter1.frozen = false; fighter2.frozen = false; } // Round yazısı var textStr = ''; var fillColor = 0xFFCC00; if (roundNum === 3) { textStr = 'FINAL ROUND'; fillColor = 0xFFD700; } else { textStr = 'ROUND ' + roundNum; fillColor = 0xFFCC00; } if (roundIntroText) { roundIntroText.destroy(); roundIntroText = null; } // Çerçeve için kutu ekle // Çerçeve kaldırıldı var roundFrame = null; roundIntroText = new Text2(textStr, { size: 220, fill: 0xffffff, font: "Impact, 'Arial Black', Tahoma, sans-serif", stroke: 0x000000, strokeThickness: 44, fontWeight: "bold", dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 8, dropShadowAngle: Math.PI / 2, dropShadowBlur: 12, dropShadowAlpha: 0.7 }); roundIntroText.anchor.set(0.5, 0.5); roundIntroText.x = 2048 / 2; roundIntroText.y = 900; game.addChild(roundIntroText); // Çerçeve ve yazıyı birlikte kaldır if (roundFrame) { roundIntroTimeouts.push(LK.setTimeout(function () { if (roundFrame) { roundFrame.destroy(); } }, 2000)); } // 2 saniye sonra "FIGHT" yazısı göster roundIntroTimeouts.push(LK.setTimeout(function () { if (roundIntroText) { roundIntroText.destroy(); roundIntroText = null; } if (fightText) { fightText.destroy(); fightText = null; } // Çerçeve için kutu ekle // Çerçeve kaldırıldı var fightFrame = null; fightText = new Text2('FIGHT', { size: 260, fill: 0xffffff, font: "Impact, 'Arial Black', Tahoma, sans-serif", stroke: 0x000000, strokeThickness: 52, fontWeight: "bold", dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 8, dropShadowAngle: Math.PI / 2, dropShadowBlur: 12, dropShadowAlpha: 0.7 }); fightText.anchor.set(0.5, 0.5); fightText.x = 2048 / 2; fightText.y = 900; game.addChild(fightText); // Çerçeve ve yazıyı birlikte kaldır if (fightFrame) { roundIntroTimeouts.push(LK.setTimeout(function () { if (fightFrame) { fightFrame.destroy(); } }, 2000)); } // 2 saniye sonra "FIGHT" yazısını fade out ile kaldır roundIntroTimeouts.push(LK.setTimeout(function () { if (fightText) { tween(fightText, { alpha: 0 }, { duration: 600, easing: tween.cubicIn, onFinish: function onFinish() { if (fightText) { fightText.destroy(); fightText = null; } if (typeof _onFinish === "function") _onFinish(); } }); } else { if (typeof _onFinish === "function") _onFinish(); } }, 2000)); }, 2000)); } // Round sonucu gösteren fonksiyonun sonunda yeni round başlatırken round intro göster // Skor ve can göstergesi (GUI) -- kaldırıldı, can barı kafanın üstünde // Oyun durumu var gameState = 'playing'; // 'playing', 'over', 'roundEnd' var dragFighter = null; var dragOffsetX = 0; var dragOffsetY = 0; // Round ve skor takibi var roundCount = 1; var playerWins = 0; var botWins = 0; var maxRounds = 3; var roundEndText = null; // Round başlatıcı fonksiyon function startRound() { // HP'leri sıfırla fighter1.hp = 100; fighter2.hp = 100; fighter1.updateHpBar(); fighter2.updateHpBar(); // Headbars full visible at round start for (var i = 0; i < 5; i++) { if (typeof headbars1 !== "undefined" && headbars1[i]) headbars1[i].alpha = 1; if (typeof headbars2 !== "undefined" && headbars2[i]) headbars2[i].alpha = 1; } // Pozisyonları ve scale'ı sıfırla fighter1.x = 2048 / 2 - 400; fighter1.y = 2050; fighter1.scaleX = 1.25; fighter1.scaleY = 1.25; fighter2.x = 2048 / 2 + 400; fighter2.y = 2050; fighter2.scaleX = 1.25; fighter2.scaleY = 1.25; // Durumları sıfırla fighter1.isAttacking = false; fighter1.isDefending = false; fighter1.isJumping = false; fighter1.attackCooldown = 0; fighter1.defendCooldown = 0; fighter2.isAttacking = false; fighter2.isDefending = false; fighter2.isJumping = false; fighter2.attackCooldown = 0; fighter2.defendCooldown = 0; // Hareketi dondurmayı kaldır (oyuncular tekrar hareket edebilsin) fighter1.frozen = false; fighter2.frozen = false; // Oyun durumunu güncelle gameState = 'playing'; } // Oyun başında ilk round intro göster showRoundIntro(roundCount, function () { startRound(); }); // Round sonucu gösteren fonksiyon function showRoundResult(winner) { gameState = 'roundEnd'; var text = ''; var fillColor = 0xffffff; // Round bitiminde hareketi dondur fighter1.frozen = true; fighter2.frozen = true; if (winner === 'player') { text = 'RED WINS'; fillColor = 0xef4244; } else if (winner === 'bot') { text = 'BLUE WINS'; fillColor = 0x3a8cff; } // Çerçeve için kutu ekle // Çerçeve kaldırıldı var resultFrame = null; roundEndText = new Text2(text, { size: 260, fill: fillColor, font: "Impact, 'Arial Black', Tahoma, sans-serif", stroke: 0xffffff, strokeThickness: 40, // much thicker stroke for extra bold dropShadow: true, dropShadowColor: 0x000000, dropShadowDistance: 8, dropShadowAngle: Math.PI / 2, dropShadowBlur: 12, dropShadowAlpha: 0.7 }); roundEndText.anchor.set(0.5, 0.5); roundEndText.x = 2048 / 2; roundEndText.y = 900; game.addChild(roundEndText); // Çerçeve ve yazıyı birlikte kaldır LK.setTimeout(function () { if (resultFrame) { resultFrame.destroy(); } }, 2000); // Sonraki round veya oyunun bitişi LK.setTimeout(function () { if (roundEndText) { roundEndText.destroy(); roundEndText = null; } // 2 galibiyet alan kazandıysa oyunu bitir if (playerWins === 2) { LK.effects.flashScreen(0x00ff00, 1000); LK.showYouWin(); } else if (botWins === 2) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } else { // Yeni round başlatmadan önce round intro göster roundCount++; showRoundIntro(roundCount, function () { startRound(); }); } }, 2000); } // Dokunma/sürükleme ile oyuncu karakterini hareket ettir game.down = function (x, y, obj) { // Multiplayer ise hangi oyuncunun dokunduğunu tespit et var playerIdx = 0; if (isMultiplayer && obj && typeof obj.playerIndex === "number") { playerIdx = obj.playerIndex; } // Sadece oyuncu karakterine dokunulduysa sürükle var local1 = fighter1.toLocal(game.toGlobal({ x: x, y: y })); var local2 = fighter2.toLocal(game.toGlobal({ x: x, y: y })); if (!isMultiplayer) { if (local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0) { dragFighter = fighter1; dragOffsetX = fighter1.x - x; dragOffsetY = fighter1.y - y; dragFighter.lastMoveY = y; } } else { // Multiplayer: iki oyuncu karşılıklı if (playerIdx === 0 && local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0) { dragFighter = fighter1; dragOffsetX = fighter1.x - x; dragOffsetY = fighter1.y - y; dragFighter.lastMoveY = y; } else if (playerIdx === 1 && local2.x > -fighter2.body.width / 2 && local2.x < fighter2.body.width / 2 && local2.y > -fighter2.body.height && local2.y < 0) { dragFighter = fighter2; dragOffsetX = fighter2.x - x; dragOffsetY = fighter2.y - y; dragFighter.lastMoveY = y; } } }; game.move = function (x, y, obj) { var playerIdx = 0; if (isMultiplayer && obj && typeof obj.playerIndex === "number") { playerIdx = obj.playerIndex; } if (dragFighter && gameState === 'playing' && !dragFighter.frozen) { // Sadece yatay eksende hareket etsin, arenadan çıkmasın var minX, maxX; if (!isMultiplayer || isMultiplayer && dragFighter === fighter1) { minX = 2048 / 2 - 700; maxX = 2048 / 2 - 100; } else { // Multiplayer ve fighter2 ise sağ tarafı sınırla minX = 2048 / 2 + 100; maxX = 2048 / 2 + 700; } var newX = x + dragOffsetX; if (newX < minX) newX = minX; if (newX > maxX) newX = maxX; dragFighter.x = newX; // Yukarıya doğru hızlı bir sürükleme ile zıpla if (typeof dragFighter.lastMoveY === "undefined") dragFighter.lastMoveY = y; var dy = dragFighter.lastMoveY - y; if (dy > 120 && !dragFighter.isJumping) { // hızlıca yukarı çekildi dragFighter.jumpAnim(); } dragFighter.lastMoveY = y; } }; game.up = function (x, y, obj) { if (dragFighter) { dragFighter.lastMoveY = undefined; } dragFighter = null; }; // Oyuncu saldırı ve savunma: ekrana çift dokunma saldırı, uzun basma savunma var lastTap = [0, 0]; var tapTimeout = [null, null]; var longPressTimeout = [null, null]; game.down = function (x, y, obj) { // Multiplayer ise hangi oyuncunun dokunduğunu tespit et var playerIdx = 0; if (isMultiplayer && obj && typeof obj.playerIndex === "number") { playerIdx = obj.playerIndex; } // Sürükleme için var local1 = fighter1.toLocal(game.toGlobal({ x: x, y: y })); var local2 = fighter2.toLocal(game.toGlobal({ x: x, y: y })); if (!isMultiplayer) { if (local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0 && !fighter1.frozen) { dragFighter = fighter1; dragOffsetX = fighter1.x - x; dragOffsetY = fighter1.y - y; // Dokunulduğu anda zıpla fighter1.jumpAnim(); } // Saldırı: çift dokunma var now = Date.now(); if (!fighter1.frozen && now - lastTap[0] < 350) { // Çift dokunma: saldırı fighter1.attackAnim(); tapTimeout[0] && LK.clearTimeout(tapTimeout[0]); } else if (!fighter1.frozen) { // Uzun basma: savunma longPressTimeout[0] = LK.setTimeout(function () { fighter1.defendAnim(); }, 400); tapTimeout[0] = LK.setTimeout(function () {}, 350); } lastTap[0] = now; } else { // Multiplayer: iki oyuncu karşılıklı if (playerIdx === 0 && local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0) { dragFighter = fighter1; dragOffsetX = fighter1.x - x; dragOffsetY = fighter1.y - y; // Dokunulduğu anda zıpla fighter1.jumpAnim(); } else if (playerIdx === 1 && local2.x > -fighter2.body.width / 2 && local2.x < fighter2.body.width / 2 && local2.y > -fighter2.body.height && local2.y < 0) { dragFighter = fighter2; dragOffsetX = fighter2.x - x; dragOffsetY = fighter2.y - y; // Dokunulduğu anda zıpla fighter2.jumpAnim(); } // Saldırı: çift dokunma var now = Date.now(); if (now - lastTap[playerIdx] < 350) { // Çift dokunma: saldırı if (playerIdx === 0) { fighter1.attackAnim(); } else { fighter2.attackAnim(); } tapTimeout[playerIdx] && LK.clearTimeout(tapTimeout[playerIdx]); } else { // Uzun basma: savunma longPressTimeout[playerIdx] = LK.setTimeout(function () { if (playerIdx === 0) { fighter1.defendAnim(); } else { fighter2.defendAnim(); } }, 400); tapTimeout[playerIdx] = LK.setTimeout(function () {}, 350); } lastTap[playerIdx] = now; } }; game.up = function (x, y, obj) { dragFighter = null; var playerIdx = 0; if (isMultiplayer && obj && typeof obj.playerIndex === "number") { playerIdx = obj.playerIndex; } if (longPressTimeout[playerIdx]) { LK.clearTimeout(longPressTimeout[playerIdx]); longPressTimeout[playerIdx] = null; } }; // Multiplayer kontrolü için oyuncu sayısı tespiti var isMultiplayer = false; if (typeof LK.getPlayerCount === "function") { // Eğer multiplayer plugin'i varsa, oyuncu sayısını al isMultiplayer = LK.getPlayerCount() > 1; } // Rakip AI: basit saldırı/savunma döngüsü (tek oyunculu modda aktif) var aiTimer = 0; var aiState = 'idle'; // 'idle', 'attack', 'defend' function aiUpdate() { if (gameState !== 'playing') return; if (isMultiplayer) return; // Multiplayer ise AI devre dışı aiTimer--; // Oyuncuya yaklaşma davranışı var distance = fighter2.x - fighter1.x; if (Math.abs(distance) > 260) { // Saldırı menziline girmediyse oyuncuya yaklaş var moveSpeed = 16; // Zıplamıyorsa hareket etsin if (!fighter2.isJumping && !fighter2.isAttacking && !fighter2.isDefending) { // Hedef pozisyonu hesapla var targetX = fighter2.x - moveSpeed; if (targetX < 2048 / 2 + 100) targetX = 2048 / 2 + 100; if (targetX > 2048 / 2 + 700) targetX = 2048 / 2 + 700; // Tween ile yumuşak hareket tween(fighter2, { x: targetX }, { duration: 80, easing: tween.cubicOut }); } aiTimer = 8; // Daha sık güncelle } else { // Saldırı/savunma döngüsü if (aiTimer <= 0) { var r = Math.random(); // Daha saldırgan: saldırı olasılığı %75, savunma %25 if (r < 0.75) { // Saldırı fighter2.attackAnim(); aiState = 'attack'; // Daha kısa bekleme, daha agresif aiTimer = 32 + Math.floor(Math.random() * 18); } else { // Savunma fighter2.defendAnim(); aiState = 'defend'; aiTimer = 48 + Math.floor(Math.random() * 24); } } } } // Saldırı çarpışma kontrolü function checkAttack() { // Oyuncu saldırısı if (fighter1.isAttacking && Math.abs(fighter1.x - fighter2.x) < 260) { if (!fighter2.isDefending && fighter2.attackCooldown <= 0) { fighter2.takeHit(18); fighter2.attackCooldown = 60; // 60 frame (~1s) cooldown, previously 20 } else if (fighter2.isDefending && fighter2.attackCooldown <= 0) { fighter2.takeHit(9); fighter2.attackCooldown = 60; } } // Rakip saldırısı if (fighter2.isAttacking && Math.abs(fighter1.x - fighter2.x) < 260) { if (!fighter1.isDefending && fighter1.attackCooldown <= 0) { fighter1.takeHit(18); fighter1.attackCooldown = 60; } else if (fighter1.isDefending && fighter1.attackCooldown <= 0) { fighter1.takeHit(9); fighter1.attackCooldown = 60; } } } // Oyun güncellemesi game.update = function () { if (gameState !== 'playing') return; fighter1.update(); fighter2.update(); aiUpdate(); checkAttack(); // Round kazananı kontrolü if (fighter1.hp <= 0 && gameState === 'playing') { botWins++; showRoundResult('bot'); } if (fighter2.hp <= 0 && gameState === 'playing') { playerWins++; showRoundResult('player'); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Dövüşçü sınıfı
var Fighter = Container.expand(function (assetId) {
var self = Container.call(this);
// Özellikler
self.hp = 100;
self.isAttacking = false;
self.isDefending = false;
self.isPlayer = false; // Oyuncu mu, rakip mi
self.attackCooldown = 0;
self.defendCooldown = 0;
self.assetId = assetId || 'fighter1'; // default to 'fighter1' if not provided
// Görsel
self.body = self.attachAsset(self.assetId, {
anchorX: 0.5,
anchorY: 1,
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 12,
dropShadowAngle: Math.PI / 2,
dropShadowBlur: 16,
dropShadowAlpha: 0.7
});
// Headbars are now managed globally, not above fighters' heads
self.hearts = [];
// Saldırı animasyonu
self.attackAnim = function () {
if (self.isAttacking || self.attackCooldown > 0) return;
self.isAttacking = true;
self.attackCooldown = 30; // 0.5 sn
var oldX = self.x;
var targetX = self.x + (self.isPlayer ? 80 : -80);
tween(self, {
x: targetX
}, {
duration: 120,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
x: oldX
}, {
duration: 120,
easing: tween.cubicIn,
onFinish: function onFinish() {
self.isAttacking = false;
}
});
}
});
};
// Savunma animasyonu
self.defendAnim = function () {
if (self.isDefending || self.defendCooldown > 0) return;
self.isDefending = true;
self.defendCooldown = 40; // 0.66 sn
tween(self.body, {
scaleX: 1.2,
scaleY: 0.8
}, {
duration: 100,
easing: tween.easeIn,
onFinish: function onFinish() {
tween(self.body, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
self.isDefending = false;
}
});
}
});
};
// Hasar alma
self.takeHit = function (amount) {
if (self.isDefending) {
amount = Math.floor(amount / 2);
}
self.hp -= amount;
if (self.hp < 0) self.hp = 0;
self.updateHpBar();
// Kırmızıya flash ve titreme efekti
LK.effects.flashObject(self.body, 0xff0000, 120);
// Titreme efekti: X ekseninde hızlıca ileri geri hareket
var originalX = self.x;
// Geriye doğru bir adım kaçma animasyonu (hasar alınan yöne göre)
// Oyuncu ise sola, rakip ise sağa kaçar
// Bot (fighter2) için: aldığı toplam hasara göre knockback mesafesini artır
var knockbackDist;
if (self.isPlayer) {
knockbackDist = -60;
} else {
// Bot için: hasar aldıkça daha fazla geri kaçar
// 100 can: 60px, 80 can: 80px, 60 can: 100px, 40 can: 120px, 20 can: 140px, 0 can: 160px
var base = 60;
var extra = Math.floor((100 - self.hp) / 20) * 20; // 0, 20, 40, 60, 80
knockbackDist = base + extra;
}
tween(self, {
x: originalX + knockbackDist
}, {
duration: 90,
easing: tween.cubicOut,
onFinish: function onFinish() {
// Titreme efekti: X ekseninde hızlıca ileri geri hareket
tween(self, {
x: originalX - 18
}, {
duration: 40,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
x: originalX + 18
}, {
duration: 40,
easing: tween.linear,
onFinish: function onFinish() {
tween(self, {
x: originalX
}, {
duration: 40,
easing: tween.linear
});
}
});
}
});
}
});
// Vuruş sesi: oyuncu ve rakip için farklı sesler
if (self.assetId === 'fighter1') {
LK.getSound('hit1').play();
} else {
LK.getSound('hit2').play();
}
};
// Can barını güncelle
self.updateHpBar = function () {
// 5 cana böl, kalan cana göre kalpleri göster/gizle
var heartsToShow = Math.ceil(self.hp / 20);
if (self.isPlayer) {
for (var i = 0; i < 5; i++) {
if (typeof headbars1 !== "undefined" && headbars1[i]) {
headbars1[i].alpha = i < heartsToShow ? 1 : 0.2;
}
}
} else {
for (var i = 0; i < 5; i++) {
if (typeof headbars2 !== "undefined" && headbars2[i]) {
headbars2[i].alpha = i < heartsToShow ? 1 : 0.2;
}
}
}
};
// Zıplama animasyonu ve durumu
self.isJumping = false;
self.jumpVy = 0;
self.jumpBaseY = 0;
self.jumpAnim = function () {
if (self.isJumping || self.isAttacking || self.isDefending) return;
self.isJumping = true;
self.jumpVy = -38; // ilk yukarı hız
self.jumpBaseY = self.y;
self.jumpHoldTimer = 0; // 2 saniye havada kalma sayacı
self.jumpState = "up"; // "up", "hold", "down"
};
self.update = function () {
if (self.attackCooldown > 0) self.attackCooldown--;
if (self.defendCooldown > 0) self.defendCooldown--;
// Zıplama güncellemesi
if (self.isJumping) {
if (self.jumpState === "up") {
self.y += self.jumpVy;
self.jumpVy += 4; // yerçekimi
if (self.jumpVy >= 0) {
// Tepeye ulaştı, 0.5 saniye havada kal
self.jumpState = "hold";
self.jumpHoldTimer = 30; // 0.5 saniye (60 FPS * 0.5)
self.jumpVy = 0;
}
} else if (self.jumpState === "hold") {
self.jumpHoldTimer--;
// Havada sabit kal
if (self.jumpHoldTimer <= 0) {
self.jumpState = "down";
self.jumpVy = 4; // Aşağıya düşmeye başla
}
} else if (self.jumpState === "down") {
self.y += self.jumpVy;
self.jumpVy += 4; // yerçekimi
if (self.y >= self.jumpBaseY) {
self.y = self.jumpBaseY;
self.isJumping = false;
self.jumpVy = 0;
self.jumpState = undefined;
self.jumpHoldTimer = 0;
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Bot için ayrı headbar asset
// Dövüşçü 1: Kırmızı kutu, Dövüşçü 2: Mavi kutu, Arenanın zemini: Geniş sarı kutu, "Fight" için: büyük metin
// Arena zemini ve dekor
var arenaFloor = LK.getAsset('arenaFloor', {
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2050
});
game.addChild(arenaFloor);
// Ejderha dekorları (üstte ve altta)
var dragonTop = LK.getAsset('dragonDeco', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: 80
});
var dragonBottom = LK.getAsset('dragonDeco', {
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2732 - 80
});
game.addChild(dragonTop);
game.addChild(dragonBottom);
// Dövüşçüler
var fighter1 = new Fighter('fighter1');
fighter1.isPlayer = true;
fighter1.scaleX = 1.25;
fighter1.scaleY = 1.25;
// Oyuncuları birbirinden uzakta başlat
fighter1.x = 2048 / 2 - 400;
fighter1.y = 2050;
game.addChild(fighter1);
var fighter2 = new Fighter('fighter2');
fighter2.isPlayer = false;
fighter2.scaleX = 1.25;
fighter2.scaleY = 1.25;
fighter2.x = 2048 / 2 + 400;
fighter2.y = 2050;
game.addChild(fighter2);
// Oyuncuyu öne getir (en üstte çizilsin)
game.addChild(fighter1);
// assetId'yi constructor parametresi olarak verelim ve Fighter class'ında kullanalım
// Headbars (health bars) at top left and top right
var headbars1 = [];
var headbars2 = [];
for (var i = 0; i < 5; i++) {
var heart1 = LK.getAsset('headBar', {
width: 110,
height: 110,
color: 0xef4244,
anchorX: 0.5,
anchorY: 0,
// Move even more inward (from 140 to 200), more spacing (from 90 to 110), and further down (from 120 to 180)
x: 200 + i * 110,
y: 120,
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 8,
dropShadowAngle: Math.PI / 2,
dropShadowBlur: 12,
dropShadowAlpha: 0.7
});
game.addChild(heart1);
headbars1.push(heart1);
var heart2 = LK.getAsset('headBarBot', {
width: 110,
height: 110,
color: 0x3a8cff,
anchorX: 0.5,
anchorY: 0,
// Move even more inward (from 140 to 200), more spacing (from 90 to 110), and further down (from 120 to 180)
x: 2048 - 200 - (4 - i) * 110,
y: 120,
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 8,
dropShadowAngle: Math.PI / 2,
dropShadowBlur: 12,
dropShadowAlpha: 0.7
});
game.addChild(heart2);
headbars2.push(heart2);
}
// Round ve intro yazılarını yönetmek için yardımcı fonksiyonlar
var roundIntroText = null;
var fightText = null;
var roundIntroTimeouts = [];
function clearRoundIntroTimeouts() {
for (var i = 0; i < roundIntroTimeouts.length; i++) {
LK.clearTimeout(roundIntroTimeouts[i]);
}
roundIntroTimeouts = [];
}
function showRoundIntro(roundNum, _onFinish) {
clearRoundIntroTimeouts();
// Dövüşçüleri round başı pozisyonlarına döndür
if (typeof fighter1 !== "undefined" && typeof fighter2 !== "undefined") {
fighter1.x = 2048 / 2 - 400;
fighter1.y = 2050;
fighter1.scaleX = 1.25;
fighter1.scaleY = 1.25;
fighter2.x = 2048 / 2 + 400;
fighter2.y = 2050;
fighter2.scaleX = 1.25;
fighter2.scaleY = 1.25;
// Saldırı/savunma/jump state sıfırla
fighter1.isAttacking = false;
fighter1.isDefending = false;
fighter1.isJumping = false;
fighter1.attackCooldown = 0;
fighter1.defendCooldown = 0;
fighter2.isAttacking = false;
fighter2.isDefending = false;
fighter2.isJumping = false;
fighter2.attackCooldown = 0;
fighter2.defendCooldown = 0;
fighter1.frozen = false;
fighter2.frozen = false;
}
// Round yazısı
var textStr = '';
var fillColor = 0xFFCC00;
if (roundNum === 3) {
textStr = 'FINAL ROUND';
fillColor = 0xFFD700;
} else {
textStr = 'ROUND ' + roundNum;
fillColor = 0xFFCC00;
}
if (roundIntroText) {
roundIntroText.destroy();
roundIntroText = null;
}
// Çerçeve için kutu ekle
// Çerçeve kaldırıldı
var roundFrame = null;
roundIntroText = new Text2(textStr, {
size: 220,
fill: 0xffffff,
font: "Impact, 'Arial Black', Tahoma, sans-serif",
stroke: 0x000000,
strokeThickness: 44,
fontWeight: "bold",
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 8,
dropShadowAngle: Math.PI / 2,
dropShadowBlur: 12,
dropShadowAlpha: 0.7
});
roundIntroText.anchor.set(0.5, 0.5);
roundIntroText.x = 2048 / 2;
roundIntroText.y = 900;
game.addChild(roundIntroText);
// Çerçeve ve yazıyı birlikte kaldır
if (roundFrame) {
roundIntroTimeouts.push(LK.setTimeout(function () {
if (roundFrame) {
roundFrame.destroy();
}
}, 2000));
}
// 2 saniye sonra "FIGHT" yazısı göster
roundIntroTimeouts.push(LK.setTimeout(function () {
if (roundIntroText) {
roundIntroText.destroy();
roundIntroText = null;
}
if (fightText) {
fightText.destroy();
fightText = null;
}
// Çerçeve için kutu ekle
// Çerçeve kaldırıldı
var fightFrame = null;
fightText = new Text2('FIGHT', {
size: 260,
fill: 0xffffff,
font: "Impact, 'Arial Black', Tahoma, sans-serif",
stroke: 0x000000,
strokeThickness: 52,
fontWeight: "bold",
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 8,
dropShadowAngle: Math.PI / 2,
dropShadowBlur: 12,
dropShadowAlpha: 0.7
});
fightText.anchor.set(0.5, 0.5);
fightText.x = 2048 / 2;
fightText.y = 900;
game.addChild(fightText);
// Çerçeve ve yazıyı birlikte kaldır
if (fightFrame) {
roundIntroTimeouts.push(LK.setTimeout(function () {
if (fightFrame) {
fightFrame.destroy();
}
}, 2000));
}
// 2 saniye sonra "FIGHT" yazısını fade out ile kaldır
roundIntroTimeouts.push(LK.setTimeout(function () {
if (fightText) {
tween(fightText, {
alpha: 0
}, {
duration: 600,
easing: tween.cubicIn,
onFinish: function onFinish() {
if (fightText) {
fightText.destroy();
fightText = null;
}
if (typeof _onFinish === "function") _onFinish();
}
});
} else {
if (typeof _onFinish === "function") _onFinish();
}
}, 2000));
}, 2000));
}
// Round sonucu gösteren fonksiyonun sonunda yeni round başlatırken round intro göster
// Skor ve can göstergesi (GUI) -- kaldırıldı, can barı kafanın üstünde
// Oyun durumu
var gameState = 'playing'; // 'playing', 'over', 'roundEnd'
var dragFighter = null;
var dragOffsetX = 0;
var dragOffsetY = 0;
// Round ve skor takibi
var roundCount = 1;
var playerWins = 0;
var botWins = 0;
var maxRounds = 3;
var roundEndText = null;
// Round başlatıcı fonksiyon
function startRound() {
// HP'leri sıfırla
fighter1.hp = 100;
fighter2.hp = 100;
fighter1.updateHpBar();
fighter2.updateHpBar();
// Headbars full visible at round start
for (var i = 0; i < 5; i++) {
if (typeof headbars1 !== "undefined" && headbars1[i]) headbars1[i].alpha = 1;
if (typeof headbars2 !== "undefined" && headbars2[i]) headbars2[i].alpha = 1;
}
// Pozisyonları ve scale'ı sıfırla
fighter1.x = 2048 / 2 - 400;
fighter1.y = 2050;
fighter1.scaleX = 1.25;
fighter1.scaleY = 1.25;
fighter2.x = 2048 / 2 + 400;
fighter2.y = 2050;
fighter2.scaleX = 1.25;
fighter2.scaleY = 1.25;
// Durumları sıfırla
fighter1.isAttacking = false;
fighter1.isDefending = false;
fighter1.isJumping = false;
fighter1.attackCooldown = 0;
fighter1.defendCooldown = 0;
fighter2.isAttacking = false;
fighter2.isDefending = false;
fighter2.isJumping = false;
fighter2.attackCooldown = 0;
fighter2.defendCooldown = 0;
// Hareketi dondurmayı kaldır (oyuncular tekrar hareket edebilsin)
fighter1.frozen = false;
fighter2.frozen = false;
// Oyun durumunu güncelle
gameState = 'playing';
}
// Oyun başında ilk round intro göster
showRoundIntro(roundCount, function () {
startRound();
});
// Round sonucu gösteren fonksiyon
function showRoundResult(winner) {
gameState = 'roundEnd';
var text = '';
var fillColor = 0xffffff;
// Round bitiminde hareketi dondur
fighter1.frozen = true;
fighter2.frozen = true;
if (winner === 'player') {
text = 'RED WINS';
fillColor = 0xef4244;
} else if (winner === 'bot') {
text = 'BLUE WINS';
fillColor = 0x3a8cff;
}
// Çerçeve için kutu ekle
// Çerçeve kaldırıldı
var resultFrame = null;
roundEndText = new Text2(text, {
size: 260,
fill: fillColor,
font: "Impact, 'Arial Black', Tahoma, sans-serif",
stroke: 0xffffff,
strokeThickness: 40,
// much thicker stroke for extra bold
dropShadow: true,
dropShadowColor: 0x000000,
dropShadowDistance: 8,
dropShadowAngle: Math.PI / 2,
dropShadowBlur: 12,
dropShadowAlpha: 0.7
});
roundEndText.anchor.set(0.5, 0.5);
roundEndText.x = 2048 / 2;
roundEndText.y = 900;
game.addChild(roundEndText);
// Çerçeve ve yazıyı birlikte kaldır
LK.setTimeout(function () {
if (resultFrame) {
resultFrame.destroy();
}
}, 2000);
// Sonraki round veya oyunun bitişi
LK.setTimeout(function () {
if (roundEndText) {
roundEndText.destroy();
roundEndText = null;
}
// 2 galibiyet alan kazandıysa oyunu bitir
if (playerWins === 2) {
LK.effects.flashScreen(0x00ff00, 1000);
LK.showYouWin();
} else if (botWins === 2) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
} else {
// Yeni round başlatmadan önce round intro göster
roundCount++;
showRoundIntro(roundCount, function () {
startRound();
});
}
}, 2000);
}
// Dokunma/sürükleme ile oyuncu karakterini hareket ettir
game.down = function (x, y, obj) {
// Multiplayer ise hangi oyuncunun dokunduğunu tespit et
var playerIdx = 0;
if (isMultiplayer && obj && typeof obj.playerIndex === "number") {
playerIdx = obj.playerIndex;
}
// Sadece oyuncu karakterine dokunulduysa sürükle
var local1 = fighter1.toLocal(game.toGlobal({
x: x,
y: y
}));
var local2 = fighter2.toLocal(game.toGlobal({
x: x,
y: y
}));
if (!isMultiplayer) {
if (local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0) {
dragFighter = fighter1;
dragOffsetX = fighter1.x - x;
dragOffsetY = fighter1.y - y;
dragFighter.lastMoveY = y;
}
} else {
// Multiplayer: iki oyuncu karşılıklı
if (playerIdx === 0 && local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0) {
dragFighter = fighter1;
dragOffsetX = fighter1.x - x;
dragOffsetY = fighter1.y - y;
dragFighter.lastMoveY = y;
} else if (playerIdx === 1 && local2.x > -fighter2.body.width / 2 && local2.x < fighter2.body.width / 2 && local2.y > -fighter2.body.height && local2.y < 0) {
dragFighter = fighter2;
dragOffsetX = fighter2.x - x;
dragOffsetY = fighter2.y - y;
dragFighter.lastMoveY = y;
}
}
};
game.move = function (x, y, obj) {
var playerIdx = 0;
if (isMultiplayer && obj && typeof obj.playerIndex === "number") {
playerIdx = obj.playerIndex;
}
if (dragFighter && gameState === 'playing' && !dragFighter.frozen) {
// Sadece yatay eksende hareket etsin, arenadan çıkmasın
var minX, maxX;
if (!isMultiplayer || isMultiplayer && dragFighter === fighter1) {
minX = 2048 / 2 - 700;
maxX = 2048 / 2 - 100;
} else {
// Multiplayer ve fighter2 ise sağ tarafı sınırla
minX = 2048 / 2 + 100;
maxX = 2048 / 2 + 700;
}
var newX = x + dragOffsetX;
if (newX < minX) newX = minX;
if (newX > maxX) newX = maxX;
dragFighter.x = newX;
// Yukarıya doğru hızlı bir sürükleme ile zıpla
if (typeof dragFighter.lastMoveY === "undefined") dragFighter.lastMoveY = y;
var dy = dragFighter.lastMoveY - y;
if (dy > 120 && !dragFighter.isJumping) {
// hızlıca yukarı çekildi
dragFighter.jumpAnim();
}
dragFighter.lastMoveY = y;
}
};
game.up = function (x, y, obj) {
if (dragFighter) {
dragFighter.lastMoveY = undefined;
}
dragFighter = null;
};
// Oyuncu saldırı ve savunma: ekrana çift dokunma saldırı, uzun basma savunma
var lastTap = [0, 0];
var tapTimeout = [null, null];
var longPressTimeout = [null, null];
game.down = function (x, y, obj) {
// Multiplayer ise hangi oyuncunun dokunduğunu tespit et
var playerIdx = 0;
if (isMultiplayer && obj && typeof obj.playerIndex === "number") {
playerIdx = obj.playerIndex;
}
// Sürükleme için
var local1 = fighter1.toLocal(game.toGlobal({
x: x,
y: y
}));
var local2 = fighter2.toLocal(game.toGlobal({
x: x,
y: y
}));
if (!isMultiplayer) {
if (local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0 && !fighter1.frozen) {
dragFighter = fighter1;
dragOffsetX = fighter1.x - x;
dragOffsetY = fighter1.y - y;
// Dokunulduğu anda zıpla
fighter1.jumpAnim();
}
// Saldırı: çift dokunma
var now = Date.now();
if (!fighter1.frozen && now - lastTap[0] < 350) {
// Çift dokunma: saldırı
fighter1.attackAnim();
tapTimeout[0] && LK.clearTimeout(tapTimeout[0]);
} else if (!fighter1.frozen) {
// Uzun basma: savunma
longPressTimeout[0] = LK.setTimeout(function () {
fighter1.defendAnim();
}, 400);
tapTimeout[0] = LK.setTimeout(function () {}, 350);
}
lastTap[0] = now;
} else {
// Multiplayer: iki oyuncu karşılıklı
if (playerIdx === 0 && local1.x > -fighter1.body.width / 2 && local1.x < fighter1.body.width / 2 && local1.y > -fighter1.body.height && local1.y < 0) {
dragFighter = fighter1;
dragOffsetX = fighter1.x - x;
dragOffsetY = fighter1.y - y;
// Dokunulduğu anda zıpla
fighter1.jumpAnim();
} else if (playerIdx === 1 && local2.x > -fighter2.body.width / 2 && local2.x < fighter2.body.width / 2 && local2.y > -fighter2.body.height && local2.y < 0) {
dragFighter = fighter2;
dragOffsetX = fighter2.x - x;
dragOffsetY = fighter2.y - y;
// Dokunulduğu anda zıpla
fighter2.jumpAnim();
}
// Saldırı: çift dokunma
var now = Date.now();
if (now - lastTap[playerIdx] < 350) {
// Çift dokunma: saldırı
if (playerIdx === 0) {
fighter1.attackAnim();
} else {
fighter2.attackAnim();
}
tapTimeout[playerIdx] && LK.clearTimeout(tapTimeout[playerIdx]);
} else {
// Uzun basma: savunma
longPressTimeout[playerIdx] = LK.setTimeout(function () {
if (playerIdx === 0) {
fighter1.defendAnim();
} else {
fighter2.defendAnim();
}
}, 400);
tapTimeout[playerIdx] = LK.setTimeout(function () {}, 350);
}
lastTap[playerIdx] = now;
}
};
game.up = function (x, y, obj) {
dragFighter = null;
var playerIdx = 0;
if (isMultiplayer && obj && typeof obj.playerIndex === "number") {
playerIdx = obj.playerIndex;
}
if (longPressTimeout[playerIdx]) {
LK.clearTimeout(longPressTimeout[playerIdx]);
longPressTimeout[playerIdx] = null;
}
};
// Multiplayer kontrolü için oyuncu sayısı tespiti
var isMultiplayer = false;
if (typeof LK.getPlayerCount === "function") {
// Eğer multiplayer plugin'i varsa, oyuncu sayısını al
isMultiplayer = LK.getPlayerCount() > 1;
}
// Rakip AI: basit saldırı/savunma döngüsü (tek oyunculu modda aktif)
var aiTimer = 0;
var aiState = 'idle'; // 'idle', 'attack', 'defend'
function aiUpdate() {
if (gameState !== 'playing') return;
if (isMultiplayer) return; // Multiplayer ise AI devre dışı
aiTimer--;
// Oyuncuya yaklaşma davranışı
var distance = fighter2.x - fighter1.x;
if (Math.abs(distance) > 260) {
// Saldırı menziline girmediyse oyuncuya yaklaş
var moveSpeed = 16;
// Zıplamıyorsa hareket etsin
if (!fighter2.isJumping && !fighter2.isAttacking && !fighter2.isDefending) {
// Hedef pozisyonu hesapla
var targetX = fighter2.x - moveSpeed;
if (targetX < 2048 / 2 + 100) targetX = 2048 / 2 + 100;
if (targetX > 2048 / 2 + 700) targetX = 2048 / 2 + 700;
// Tween ile yumuşak hareket
tween(fighter2, {
x: targetX
}, {
duration: 80,
easing: tween.cubicOut
});
}
aiTimer = 8; // Daha sık güncelle
} else {
// Saldırı/savunma döngüsü
if (aiTimer <= 0) {
var r = Math.random();
// Daha saldırgan: saldırı olasılığı %75, savunma %25
if (r < 0.75) {
// Saldırı
fighter2.attackAnim();
aiState = 'attack';
// Daha kısa bekleme, daha agresif
aiTimer = 32 + Math.floor(Math.random() * 18);
} else {
// Savunma
fighter2.defendAnim();
aiState = 'defend';
aiTimer = 48 + Math.floor(Math.random() * 24);
}
}
}
}
// Saldırı çarpışma kontrolü
function checkAttack() {
// Oyuncu saldırısı
if (fighter1.isAttacking && Math.abs(fighter1.x - fighter2.x) < 260) {
if (!fighter2.isDefending && fighter2.attackCooldown <= 0) {
fighter2.takeHit(18);
fighter2.attackCooldown = 60; // 60 frame (~1s) cooldown, previously 20
} else if (fighter2.isDefending && fighter2.attackCooldown <= 0) {
fighter2.takeHit(9);
fighter2.attackCooldown = 60;
}
}
// Rakip saldırısı
if (fighter2.isAttacking && Math.abs(fighter1.x - fighter2.x) < 260) {
if (!fighter1.isDefending && fighter1.attackCooldown <= 0) {
fighter1.takeHit(18);
fighter1.attackCooldown = 60;
} else if (fighter1.isDefending && fighter1.attackCooldown <= 0) {
fighter1.takeHit(9);
fighter1.attackCooldown = 60;
}
}
}
// Oyun güncellemesi
game.update = function () {
if (gameState !== 'playing') return;
fighter1.update();
fighter2.update();
aiUpdate();
checkAttack();
// Round kazananı kontrolü
if (fighter1.hp <= 0 && gameState === 'playing') {
botWins++;
showRoundResult('bot');
}
if (fighter2.hp <= 0 && gameState === 'playing') {
playerWins++;
showRoundResult('player');
}
};