/**** * 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');
}
};