User prompt
Please fix the bug: 'TypeError: Cannot use 'in' operator to search for 'scaleX' in null' in or related to this line: 'tween(hiori.flowText, {' Line Number: 931 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Kaldır Flow dışı Monster Trans ı
User prompt
Monster Trans Flow formu olacak Bachira nın topu aldığı gibi Monster Trans a geçmesin sadece Roullet ve Monster Dribbling y apsın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Monster Trans a toplam 2 tarafta mesela Player 1 - Oppenent 2 ise Bachira diyerleri gibi rastgele bir şansla Flow açar garanti Hiori her zaman Flow açmasın Bachira nın Flow u Monster Trans ve Dribbling ile geçtiği herkez Stun yesin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Roullet sonrası topu kenara atıp birden topa hızlanıp Topu bizim gibi kaleye atabilsin ! ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Meguru Bachira ekle ! Roullet, Moster Dribbling kullana bilsin Flow dayken Monster Trans a geçsin hızı Dribbling yeteneklerinin Cooldown ı olmasın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Nagi başlangıçta Flow da olmasın ve Nagi ye Fake atma ekle Nagi nin bazı vuruşları Fake olsun ve Rakibi Stun lasın 5 ila 10 saniye rastgele Cooldown gelsin buna göre ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sae bizim kalenin altında duruyor sürekli düzelt ve Dribbling leri daha az mesafe kat etsin Nerf getir Sae ye kısaca ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Nagi ye Flow açtırt oyun başında
User prompt
Nagi 5 Revolver Fake Volley yapabilsin Flow a geçtiğinde takımdaki rastgele bir oyuncuya Flow gelsen 2 gol sonra bide ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sae de 2 Gol atınca Flow a girsin ve Hilal şeklinde Dribble atsın sürekli ve en sonunda kaleye şut çeksin bir forvet gibi ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
6 Zig zag atabilsin ve Dash 10 saniyede bir atsın Chop un menzilini kısalt ve Sae sürekli aktif olsun ve uzaktan Falsolu şut çekmeye ayarla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sae Zig zag ve Chop Dribbling de yapabilsin ve Devoured olsun her dribbling ile geçtiği kişi hızları falan düşsün stun lansınlar veya %30 şansla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sae ekle karşı tarafa Perfect Pas ı olsun yarım daire çizerek Dribbling atabilsin oyun stun yesin Dribbling bitene kadar Dash atabilsin ufak çaplı ve Falsolu vuruş yapabilsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Hiori ye Flow yap Hiori Flow dayken ekstra 4 tane daha dribbling yapsın bide Winter Zone çok daha fazla yavaşlatsın ekstra pas atacaksa direk top bize gelsin ve Winter Zone çok daha büyük olsun Flow gereksinimi 2 Gol yememiz ve rastgele bir oyuncu flow a girecek yani burada o kişi Hiori oluyor
User prompt
Nagi rakip kaleye gitsin o pozisyonda ve Reo da çok daha aktif olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Nagi topu Rakibin ayağındanda çalabilsin Ball Control ile Hiori nin Winter Zone undan biraz daha gküçük bir alana etki edecek ve Nagi den 3 saniye boyunca top çalamayacaklar ve Nagi sadece Gol atmaya odaklanacak ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Chigiri nin Staminası bitince baya bi yavaşlasın
User prompt
Top otomatik Nagi nin ayağına gelsin Ball Control yazzsın üstünde ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Nagi ekle ! Fake Vole 1 kere Fake vuruş yapıp Rakibi şaşırtıp Stun layıp yani Gerçek vuruşu yapsın 2. vuruşta Topu kendine çekebilsin çekeceği zaman etrafındaki menzili yani alanı göster ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Reo Npc lerin Winter Zone gibi yeteneklerinide kopyalayıp kullanabilsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var ChigiriPlayer = Container.expand(function (colorOverride) { var self = Container.call(this); var opponentGraphics = self.attachAsset('opponent', { anchorX: 0.5, anchorY: 0.5 }); if (typeof colorOverride === "number" && opponentGraphics) { opponentGraphics.tint = colorOverride; } self.speed = 5; self.role = 'chigiri'; self.homeX = 800; self.homeY = 2000; self.maxDistance = 600; self.hasBall = false; self.isSpeedBursting = false; self.speedBurstTarget = null; self.speedBurstCooldown = 0; self.speedBurstCooldownTime = 8000; // 8 seconds self.normalSpeed = 5; self.burstSpeed = 12; self.update = function () { // Update speed burst cooldown if (self.speedBurstCooldown > 0) { self.speedBurstCooldown -= 16; if (self.speedBurstCooldown < 0) self.speedBurstCooldown = 0; } // Steal ball if opponent is inside area var nearestOpponent = null; var nearestDistance = Infinity; for (var i = 0; i < opponents.length; i++) { var opponentDist = Math.sqrt((opponents[i].x - self.x) * (opponents[i].x - self.x) + (opponents[i].y - self.y) * (opponents[i].y - self.y)); if (opponentDist < nearestDistance) { nearestDistance = opponentDist; nearestOpponent = opponents[i]; } } if (nearestOpponent && nearestDistance < 80 && nearestOpponent.hasBall) { // Steal the ball nearestOpponent.hasBall = false; ball.active = true; // Ball moves toward Chigiri var stealDx = self.x - nearestOpponent.x; var stealDy = self.y - nearestOpponent.y; var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy); if (stealDist > 0) { ball.velocityX = stealDx / stealDist * 8; ball.velocityY = stealDy / stealDist * 8; } ballDetachCooldown = ballDetachCooldownTime; } var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Enhanced ball pursuit for hybrid player if (distance < 500 && !self.isSpeedBursting) { // Chase ball with hybrid intelligence var chaseSpeed = distance < 150 ? self.normalSpeed * 1.4 : self.normalSpeed * 1.1; self.x += dx / distance * chaseSpeed; self.y += dy / distance * chaseSpeed; } // Speed burst mechanic if (!self.isSpeedBursting && self.speedBurstCooldown <= 0 && distance < 100) { // Throw ball forward and start speed burst var throwX = opponentGoal.x + (Math.random() - 0.5) * 200; var throwY = opponentGoal.y + 200; var throwDx = throwX - ball.x; var throwDy = throwY - ball.y; var throwDist = Math.sqrt(throwDx * throwDx + throwDy * throwDy); if (throwDist > 0) { ball.velocityX = throwDx / throwDist * 14; ball.velocityY = throwDy / throwDist * 14; } // Set speed burst target and activate self.speedBurstTarget = { x: throwX, y: throwY }; self.isSpeedBursting = true; self.speedBurstCooldown = self.speedBurstCooldownTime; // Start cooldown // Visual effect for speed burst tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); } if (self.isSpeedBursting && self.speedBurstTarget) { // Move at burst speed toward target var burstDx = self.speedBurstTarget.x - self.x; var burstDy = self.speedBurstTarget.y - self.y; var burstDist = Math.sqrt(burstDx * burstDx + burstDy * burstDy); if (burstDist > 30) { self.x += burstDx / burstDist * self.burstSpeed; self.y += burstDy / burstDist * self.burstSpeed; } else { // Reached target, stop speed burst self.isSpeedBursting = false; self.speedBurstTarget = null; } } else { // Normal hybrid behavior - enhanced ball pursuit if (distance < 500) { // Move toward ball with improved midfielder intelligence var pursuitSpeed = distance < 200 ? self.normalSpeed * 1.3 : self.normalSpeed * 1.1; self.x += dx / distance * pursuitSpeed; self.y += dy / distance * pursuitSpeed; // Attack opponent goal if close to ball if (distance < 80) { var goalDx = opponentGoal.x - ball.x; var goalDy = opponentGoal.y - ball.y; var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy); if (goalDistance > 0) { ball.velocityX = goalDx / goalDistance * 11; ball.velocityY = goalDy / goalDistance * 11; } } } else { // Return to defensive position var homeDx = self.homeX - self.x; var homeDy = self.homeY - self.y; var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy); if (homeDistance > 50) { self.x += homeDx / homeDistance * self.normalSpeed * 0.4; self.y += homeDy / homeDistance * self.normalSpeed * 0.4; } } } }; return self; }); var DefensePlayer = Container.expand(function (colorOverride) { var self = Container.call(this); var opponentGraphics = self.attachAsset('opponent', { anchorX: 0.5, anchorY: 0.5 }); if (typeof colorOverride === "number" && opponentGraphics) { opponentGraphics.tint = colorOverride; } self.speed = 4; self.role = 'defense'; self.homeX = 1024; self.homeY = 600; self.maxDistance = 400; self.hasBall = false; self.update = function () { // Steal ball if player is inside opponent var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y)); if (playerDist < 80 && player.hasBall) { // Steal the ball player.hasBall = false; ball.active = true; // Ball moves away from player, toward defense var stealDx = self.x - player.x; var stealDy = self.y - player.y; var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy); if (stealDist > 0) { ball.velocityX = stealDx / stealDist * 10; ball.velocityY = stealDy / stealDist * 10; } // Prevent immediate re-attachment ballDetachCooldown = ballDetachCooldownTime; } var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Defense priority: desperately try to get the ball if (distance < 400) { // Move aggressively toward ball - increased chase range self.x += dx / distance * (self.speed * 1.2); self.y += dy / distance * (self.speed * 1.2); // Sliding tackle if player is close to defense var playerDistance = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y)); if (playerDistance < 120 && ball.active && !player.hasBall) { // Slide tackle: dash toward ball and clear it away var slideDx = ball.x - self.x; var slideDy = ball.y - self.y; var slideDist = Math.sqrt(slideDx * slideDx + slideDy * slideDy); if (slideDist > 0) { // Animate slide (quick move) tween(self, { x: self.x + slideDx / slideDist * 60, y: self.y + slideDy / slideDist * 60 }, { duration: 120, easing: tween.cubicOut }); // Clear ball far away from player var clearX = ball.x < 1024 ? ball.x - 400 : ball.x + 400; var clearY = ball.y - 500; var clearDx = clearX - ball.x; var clearDy = clearY - ball.y; var clearDist = Math.sqrt(clearDx * clearDx + clearDy * clearDy); if (clearDist > 0) { ball.velocityX = clearDx / clearDist * 13; ball.velocityY = clearDy / clearDist * 13; } } } // Kick ball away from player goal if close enough if (distance < 80) { // Find nearest forward player var nearestForward = null; var nearestDistance = Infinity; for (var i = 0; i < opponents.length; i++) { if (opponents[i].role === 'forward') { var forwardDx = opponents[i].x - self.x; var forwardDy = opponents[i].y - self.y; var forwardDistance = Math.sqrt(forwardDx * forwardDx + forwardDy * forwardDy); if (forwardDistance < nearestDistance) { nearestDistance = forwardDistance; nearestForward = opponents[i]; } } } // Pass to forward if found, otherwise clear as before if (nearestForward) { var passDx = nearestForward.x - ball.x; var passDy = nearestForward.y - ball.y; var passDistance = Math.sqrt(passDx * passDx + passDy * passDy); if (passDistance > 0) { ball.velocityX = passDx / passDistance * 10; ball.velocityY = passDy / passDistance * 10; } } else { var kickAwayX = ball.x < 1024 ? ball.x - 200 : ball.x + 200; var kickAwayY = ball.y - 300; // Kick upfield var kickDx = kickAwayX - ball.x; var kickDy = kickAwayY - ball.y; var kickDistance = Math.sqrt(kickDx * kickDx + kickDy * kickDy); if (kickDistance > 0) { ball.velocityX = kickDx / kickDistance * 8; ball.velocityY = kickDy / kickDistance * 8; } } } } else { // Return to defensive position var homeDx = self.homeX - self.x; var homeDy = self.homeY - self.y; var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy); if (homeDistance > 50) { self.x += homeDx / homeDistance * self.speed * 0.5; self.y += homeDy / homeDistance * self.speed * 0.5; } } }; return self; }); var ForwardPlayer = Container.expand(function () { var self = Container.call(this); var opponentGraphics = self.attachAsset('opponent', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3.5; self.role = 'forward'; self.homeX = 1024; self.homeY = 1400; self.hasBall = false; self.directShotCooldown = self.directShotCooldown || 0; self.update = function () { // Steal ball if player is inside opponent var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y)); if (playerDist < 80 && player.hasBall) { // Steal the ball player.hasBall = false; ball.active = true; // Ball moves away from player, toward forward var stealDx = self.x - player.x; var stealDy = self.y - player.y; var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy); if (stealDist > 0) { ball.velocityX = stealDx / stealDist * 10; ball.velocityY = stealDy / stealDist * 10; } // Prevent immediate re-attachment ballDetachCooldown = ballDetachCooldownTime; } // Handle direct shot cooldown if (self.directShotCooldown > 0) { self.directShotCooldown -= 16; if (self.directShotCooldown < 0) self.directShotCooldown = 0; } var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Forward: attack and try to score if (distance < 400) { // Move toward ball with aggressive pursuit var pursuitSpeed = distance < 200 ? self.speed * 1.8 : self.speed * 1.3; self.x += dx / distance * pursuitSpeed; self.y += dy / distance * pursuitSpeed; // If close to ball, shoot at goal if (distance < 80) { // Direct Shot every 30s if (self.directShotCooldown <= 0) { var goalDx = playerGoal.x - ball.x; var goalDy = playerGoal.y - ball.y; var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy); if (goalDistance > 0) { // Direct Shot: very fast and straight ball.velocityX = goalDx / goalDistance * 18; ball.velocityY = goalDy / goalDistance * 18; } self.directShotCooldown = 30000; // 30 seconds } else { // Normal shot var goalDx = playerGoal.x - ball.x; var goalDy = playerGoal.y - ball.y; var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy); if (goalDistance > 0) { ball.velocityX = goalDx / goalDistance * 10; ball.velocityY = goalDy / goalDistance * 10; } } } } else { // Move toward attacking position var homeDx = self.homeX - self.x; var homeDy = self.homeY - self.y; var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy); if (homeDistance > 50) { self.x += homeDx / homeDistance * self.speed * 0.4; self.y += homeDy / homeDistance * self.speed * 0.4; } } }; return self; }); var Goal = Container.expand(function () { var self = Container.call(this); // Goal area var goalGraphics = self.attachAsset('goal', { anchorX: 0.5, anchorY: 0.5 }); goalGraphics.alpha = 0.3; // Left goalpost var leftPost = self.addChild(LK.getAsset('goalpost', { anchorX: 0.5, anchorY: 0.5 })); leftPost.x = -210; leftPost.y = 0; // Right goalpost var rightPost = self.addChild(LK.getAsset('goalpost', { anchorX: 0.5, anchorY: 0.5 })); rightPost.x = 210; rightPost.y = 0; return self; }); var Goalkeeper = Container.expand(function (isPlayer) { var self = Container.call(this); var keeperGraphics = self.attachAsset(isPlayer ? 'player' : 'opponent', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.isPlayer = isPlayer; self.rushCooldown = 0; self.rushCooldownTime = 20000; // 20 seconds self.isRushing = false; self.originalX = 0; self.originalY = 0; self.rushSpeed = 8; self.update = function () { // Update rush cooldown if (self.rushCooldown > 0) { self.rushCooldown -= 16; // Approximately 60 FPS if (self.rushCooldown < 0) self.rushCooldown = 0; } // Check if should rush for ball var ballDistance = Math.sqrt((ball.x - self.x) * (ball.x - self.x) + (ball.y - self.y) * (ball.y - self.y)); if (!self.isRushing && self.rushCooldown <= 0 && ballDistance < 400) { // Start rushing self.isRushing = true; self.rushCooldown = self.rushCooldownTime; } if (self.isRushing) { // Rush toward ball var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0 && distance > 50) { self.x += dx / distance * self.rushSpeed; self.y += dy / distance * self.rushSpeed; } else if (distance <= 50) { // Catch ball if close enough ball.velocityX = 0; ball.velocityY = 0; ball.x = self.x; ball.y = self.y; ball.active = false; player.hasBall = false; // Return to original position first self.isRushing = false; tween(self, { x: self.originalX, y: self.originalY }, { duration: 1000, onFinish: function onFinish() { // After returning to position, throw ball to center field ball.active = true; var centerX = 1024; var centerY = 1366; var throwPower = 15; var throwDx = centerX - ball.x; var throwDy = centerY - ball.y; var throwDistance = Math.sqrt(throwDx * throwDx + throwDy * throwDy); if (throwDistance > 0) { ball.velocityX = throwDx / throwDistance * throwPower; ball.velocityY = throwDy / throwDistance * throwPower; } } }); } } else { // Normal goalkeeper movement - stay near goal line var goalCenterX = 1024; var dx = goalCenterX - self.x; if (Math.abs(dx) > 5) { self.x += dx > 0 ? self.speed : -self.speed; } } }; return self; }); var HioriPlayer = Container.expand(function (colorOverride) { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); if (typeof colorOverride === "number" && playerGraphics) { playerGraphics.tint = colorOverride; } self.speed = 4; self.role = 'hiori'; self.homeX = 1200; self.homeY = 2000; self.hasBall = false; // Zig-zag dribbling variables self.isDribbling = false; self.dribbleStartTime = 0; self.dribbleDuration = 2000; // 2 seconds - slower duration self.dribbleSpeed = 6; self.dribbleDirection = 1; // 1 for right, -1 for left self.dribblePhase = 0; // 0-1 progress through dribble self.dribbleStartX = 0; self.dribbleStartY = 0; self.dribbleTargetX = 0; self.dribbleTargetY = 0; // Zigzag pause variables self.zigzagCount = 0; self.zigzagPaused = false; self.zigzagPauseStart = 0; self.zigzagPauseDuration = 10000; // 10 seconds // Winter Zone variables self.winterZoneActive = false; self.winterZoneRadius = 200; self.winterZoneCooldown = 0; self.winterZoneCooldownTime = 12000; // 12 seconds self.winterZoneDuration = 0; self.winterZoneMaxDuration = 10000; // 10 seconds - increased duration self.slowedOpponents = []; // Winter Zone visual self.winterZoneVisual = null; // Perfect pass variables self.passChargingTime = 0; self.perfectPassCooldown = 0; self.perfectPassCooldownTime = 6000; // 6 seconds self.update = function () { // Update cooldowns if (self.winterZoneCooldown > 0) { self.winterZoneCooldown -= 16; if (self.winterZoneCooldown < 0) self.winterZoneCooldown = 0; } if (self.perfectPassCooldown > 0) { self.perfectPassCooldown -= 16; if (self.perfectPassCooldown < 0) self.perfectPassCooldown = 0; } // Winter Zone duration and effect if (self.winterZoneActive) { self.winterZoneDuration -= 16; if (self.winterZoneDuration <= 0) { self.winterZoneActive = false; // Remove Winter Zone visual if (self.winterZoneVisual) { self.winterZoneVisual.destroy(); self.winterZoneVisual = null; } // Restore opponent speeds for (var i = 0; i < self.slowedOpponents.length; i++) { var opponent = self.slowedOpponents[i]; opponent.speed = opponent.originalSpeed || opponent.speed * 2; } self.slowedOpponents = []; } else { // Apply Winter Zone effect to nearby opponents for (var i = 0; i < opponents.length; i++) { var opponent = opponents[i]; var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y)); if (dist <= self.winterZoneRadius) { if (self.slowedOpponents.indexOf(opponent) === -1) { opponent.originalSpeed = opponent.speed; opponent.speed = opponent.speed * 0.3; // Slow to 30% speed self.slowedOpponents.push(opponent); } } } } } var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Zig-zag dribbling logic if (self.isDribbling) { var elapsed = Date.now() - self.dribbleStartTime; var progress = Math.min(elapsed / self.dribbleDuration, 1); // Create zig-zag pattern - slower frequency for better visibility var zigzagAmplitude = 80; var zigzagFrequency = 4; var zigzagOffset = Math.sin(progress * Math.PI * zigzagFrequency) * zigzagAmplitude; // Move toward target with zig-zag motion - slower speed var targetDx = self.dribbleTargetX - self.dribbleStartX; var targetDy = self.dribbleTargetY - self.dribbleStartY; var targetDist = Math.sqrt(targetDx * targetDx + targetDy * targetDy); if (targetDist > 0) { // Calculate perpendicular vector for zig-zag var perpX = -targetDy / targetDist; var perpY = targetDx / targetDist; // Apply zig-zag movement with slower speed var slowSpeed = 0.6; // Reduced from 1.0 to make it slower self.x = self.dribbleStartX + targetDx * progress * slowSpeed + perpX * zigzagOffset; self.y = self.dribbleStartY + targetDy * progress * slowSpeed + perpY * zigzagOffset; // Ball follows during dribble if (distance < 100) { ball.x = self.x; ball.y = self.y; ball.velocityX = 0; ball.velocityY = 0; } } // End dribbling if (progress >= 1) { self.isDribbling = false; self.zigzagCount = (self.zigzagCount || 0) + 1; // After 4 zigzags, pause for 10 seconds if (self.zigzagCount >= 4) { self.zigzagPaused = true; self.zigzagPauseStart = Date.now(); self.zigzagCount = 0; } } } else { // Normal ball pursuit if (distance < 400) { var chaseSpeed = distance < 150 ? self.speed * 1.3 : self.speed * 1.1; self.x += dx / distance * chaseSpeed; self.y += dy / distance * chaseSpeed; // Handle zigzag pause if (self.zigzagPaused) { var pauseElapsed = Date.now() - self.zigzagPauseStart; if (pauseElapsed >= self.zigzagPauseDuration) { self.zigzagPaused = false; } } // Start zig-zag dribbling when close to ball (only if not paused) if (distance < 80 && !self.isDribbling && !self.zigzagPaused) { self.isDribbling = true; self.dribbleStartTime = Date.now(); self.dribbleStartX = self.x; self.dribbleStartY = self.y; // Dribble toward opponent goal self.dribbleTargetX = opponentGoal.x + (Math.random() - 0.5) * 300; self.dribbleTargetY = opponentGoal.y + 200; } } } // Activate Winter Zone when opponents get close if (!self.winterZoneActive && self.winterZoneCooldown <= 0) { var nearbyOpponents = 0; for (var i = 0; i < opponents.length; i++) { var opponent = opponents[i]; var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y)); if (dist <= self.winterZoneRadius + 50) { nearbyOpponents++; } } if (nearbyOpponents >= 2) { // Activate Winter Zone self.winterZoneActive = true; self.winterZoneDuration = self.winterZoneMaxDuration; self.winterZoneCooldown = self.winterZoneCooldownTime; // Create Winter Zone visual area self.winterZoneVisual = self.addChild(LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 4, tint: 0x87CEEB })); self.winterZoneVisual.alpha = 0.3; // Visual effect tween(self, { scaleX: 1.5, scaleY: 1.5, tint: 0x87CEEB }, { duration: 200, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1, tint: 0xFFFFFF }, { duration: 200 }); } }); } } // Perfect deceptive pass when close to ball if (distance < 80 && self.perfectPassCooldown <= 0) { // Look for player to pass to var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y)); if (playerDist < 600 && playerDist > 100) { // Execute perfect deceptive pass var passDx = player.x - ball.x; var passDy = player.y - ball.y; var passDist = Math.sqrt(passDx * passDx + passDy * passDy); if (passDist > 0) { // Perfect pass with slight curve to avoid interception var curveAmount = 3; ball.velocityX = passDx / passDist * 12 + curveAmount; ball.velocityY = passDy / passDist * 12; ball.active = true; self.perfectPassCooldown = self.perfectPassCooldownTime; // Visual effect for perfect pass tween(ball, { scaleX: 1.3, scaleY: 1.3 }, { duration: 150, onFinish: function onFinish() { tween(ball, { scaleX: 1, scaleY: 1 }, { duration: 150 }); } }); } } } // Return to home position when not actively playing if (distance > 500) { var homeDx = self.homeX - self.x; var homeDy = self.homeY - self.y; var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy); if (homeDistance > 50) { self.x += homeDx / homeDistance * self.speed * 0.4; self.y += homeDy / homeDistance * self.speed * 0.4; } } }; return self; }); var MidfieldPlayer = Container.expand(function () { var self = Container.call(this); var opponentGraphics = self.attachAsset('opponent', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.role = 'midfield'; self.homeX = 1024; self.homeY = 1000; self.hasBall = false; // Dribbling state self.isDribbling = false; self.dribbleStartTime = 0; self.dribbleDuration = 1000; self.dribbleRadius = 120; self.dribbleStartAngle = 0; self.dribbleEndAngle = 0; self.dribbleOriginX = 0; self.dribbleOriginY = 0; self.hasDribbled = false; self.update = function () { // Steal ball if player is inside opponent var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y)); if (playerDist < 80 && player.hasBall) { // Steal the ball player.hasBall = false; ball.active = true; // Ball moves away from player, toward midfield var stealDx = self.x - player.x; var stealDy = self.y - player.y; var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy); if (stealDist > 0) { ball.velocityX = stealDx / stealDist * 10; ball.velocityY = stealDy / stealDist * 10; } // Prevent immediate re-attachment ballDetachCooldown = ballDetachCooldownTime; } var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Midfield: get ball and pass to forward if (distance < 350) { // Move toward ball with increased speed when chasing var chaseSpeed = distance < 150 ? self.speed * 1.5 : self.speed * 1.2; self.x += dx / distance * chaseSpeed; self.y += dy / distance * chaseSpeed; // If close to ball, run away from player and pass to forward if (distance < 80) { // Move away from player for a moment var awayDx = self.x - player.x; var awayDy = self.y - player.y; var awayDist = Math.sqrt(awayDx * awayDx + awayDy * awayDy); if (awayDist > 0) { tween(self, { x: self.x + awayDx / awayDist * 120, y: self.y + awayDy / awayDist * 120 }, { duration: 200, easing: tween.cubicOut }); } // Find nearest forward player var nearestForward = null; var nearestDistance = Infinity; for (var i = 0; i < opponents.length; i++) { if (opponents[i].role === 'forward') { var forwardDx = opponents[i].x - self.x; var forwardDy = opponents[i].y - self.y; var forwardDistance = Math.sqrt(forwardDx * forwardDx + forwardDy * forwardDy); if (forwardDistance < nearestDistance) { nearestDistance = forwardDistance; nearestForward = opponents[i]; } } } // Pass to forward if found if (nearestForward) { // Perfect pass: ball goes directly to forward with good speed var passDx = nearestForward.x - ball.x; var passDy = nearestForward.y - ball.y; var passDistance = Math.sqrt(passDx * passDx + passDy * passDy); if (passDistance > 0) { ball.velocityX = passDx / passDistance * 10; ball.velocityY = passDy / passDistance * 10; } } else { // No forward to pass to: perform dribbling and curved shot if (!self.isDribbling) { // Start dribbling: move in a half-circle around the player self.isDribbling = true; self.dribbleStartTime = Date.now(); self.dribbleDuration = 1000; // 1 second self.dribbleRadius = 120; // Calculate angle from midfield to player var angleToPlayer = Math.atan2(player.y - self.y, player.x - self.x); self.dribbleStartAngle = angleToPlayer - Math.PI / 2; self.dribbleEndAngle = angleToPlayer + Math.PI / 2; self.dribbleOriginX = self.x; self.dribbleOriginY = self.y; self.hasDribbled = false; } if (self.isDribbling) { var elapsed = Date.now() - self.dribbleStartTime; var t = Math.min(elapsed / self.dribbleDuration, 1); // Interpolate angle for half-circle var angle = self.dribbleStartAngle + (self.dribbleEndAngle - self.dribbleStartAngle) * t; self.x = self.dribbleOriginX + Math.cos(angle) * self.dribbleRadius; self.y = self.dribbleOriginY + Math.sin(angle) * self.dribbleRadius; // Ball follows midfield during dribble if (distance < 80) { ball.x = self.x; ball.y = self.y; ball.velocityX = 0; ball.velocityY = 0; } // When dribble completes, shoot with curve if (t >= 1 && !self.hasDribbled) { self.hasDribbled = true; self.isDribbling = false; // Falsolu şut: apply curve by adding to X velocity var goalDx = opponentGoal.x - ball.x; var goalDy = opponentGoal.y - ball.y; var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy); if (goalDistance > 0) { // Add curve: right-footed, so curve to the right (positive X) var curveAmount = 7; ball.velocityX = goalDx / goalDistance * 12 + curveAmount; ball.velocityY = goalDy / goalDistance * 12; ball.active = true; } } } } } } else { // Return to midfield position var homeDx = self.homeX - self.x; var homeDy = self.homeY - self.y; var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy); if (homeDistance > 50) { self.x += homeDx / homeDistance * self.speed * 0.3; self.y += homeDy / homeDistance * self.speed * 0.3; } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.hasBall = false; return self; }); var ReoPlayer = Container.expand(function (colorOverride) { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); if (typeof colorOverride === "number" && playerGraphics) { playerGraphics.tint = colorOverride; } self.speed = 4; self.role = 'reo'; self.homeX = 600; self.homeY = 1800; self.hasBall = false; // Mode switching variables self.isDefensiveMode = true; self.defensiveColor = 0x000000; // Black self.attackingColor = 0xffa500; // Orange self.modeSwitch = 0; self.modeSwitchInterval = 5000; // 5 seconds // Chameleon ability variables self.chameleonCooldown = 0; self.chameleonInterval = 30000; // 30 seconds self.copiedStats = null; self.originalSpeed = 4; self.originalDribbling = 1; self.originalShot = 1; // Copied ability variables self.copiedWinterZone = false; self.copiedWinterZoneRadius = 200; self.copiedWinterZoneCooldown = 0; self.copiedWinterZoneActive = false; self.copiedWinterZoneDuration = 0; self.copiedWinterZoneMaxDuration = 8000; self.copiedSlowedOpponents = []; self.copiedWinterZoneVisual = null; self.copiedSpeedBurst = false; self.copiedSpeedBurstCooldown = 0; self.copiedSpeedBurstActive = false; self.copiedBurstSpeed = 10; self.copiedNormalSpeed = 4; self.update = function () { // Update mode switching self.modeSwitch += 16; if (self.modeSwitch >= self.modeSwitchInterval) { self.modeSwitch = 0; self.isDefensiveMode = !self.isDefensiveMode; // Change color based on mode if (self.isDefensiveMode) { tween(playerGraphics, { tint: self.defensiveColor }, { duration: 300 }); } else { tween(playerGraphics, { tint: self.attackingColor }, { duration: 300 }); } } // Update Chameleon cooldown self.chameleonCooldown += 16; if (self.chameleonCooldown >= self.chameleonInterval) { self.chameleonCooldown = 0; self.activateChameleon(); } // Update copied abilities if (self.copiedWinterZone) { // Update Winter Zone cooldown if (self.copiedWinterZoneCooldown > 0) { self.copiedWinterZoneCooldown -= 16; if (self.copiedWinterZoneCooldown < 0) self.copiedWinterZoneCooldown = 0; } // Winter Zone duration and effect if (self.copiedWinterZoneActive) { self.copiedWinterZoneDuration -= 16; if (self.copiedWinterZoneDuration <= 0) { self.copiedWinterZoneActive = false; // Remove Winter Zone visual if (self.copiedWinterZoneVisual) { self.copiedWinterZoneVisual.destroy(); self.copiedWinterZoneVisual = null; } // Restore opponent speeds for (var i = 0; i < self.copiedSlowedOpponents.length; i++) { var opponent = self.copiedSlowedOpponents[i]; opponent.speed = opponent.originalSpeed || opponent.speed * 2; } self.copiedSlowedOpponents = []; } else { // Apply Winter Zone effect to nearby opponents for (var i = 0; i < opponents.length; i++) { var opponent = opponents[i]; var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y)); if (dist <= self.copiedWinterZoneRadius) { if (self.copiedSlowedOpponents.indexOf(opponent) === -1) { opponent.originalSpeed = opponent.speed; opponent.speed = opponent.speed * 0.3; // Slow to 30% speed self.copiedSlowedOpponents.push(opponent); } } } } } // Activate Winter Zone when opponents get close if (!self.copiedWinterZoneActive && self.copiedWinterZoneCooldown <= 0) { var nearbyOpponents = 0; for (var i = 0; i < opponents.length; i++) { var opponent = opponents[i]; var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y)); if (dist <= self.copiedWinterZoneRadius + 50) { nearbyOpponents++; } } if (nearbyOpponents >= 2) { // Activate Winter Zone self.copiedWinterZoneActive = true; self.copiedWinterZoneDuration = self.copiedWinterZoneMaxDuration; self.copiedWinterZoneCooldown = 12000; // 12 seconds cooldown // Create Winter Zone visual area self.copiedWinterZoneVisual = self.addChild(LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 4, scaleY: 4, tint: 0x87CEEB })); self.copiedWinterZoneVisual.alpha = 0.3; // Visual effect tween(self, { scaleX: 1.5, scaleY: 1.5, tint: 0x87CEEB }, { duration: 200, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1, tint: self.isDefensiveMode ? self.defensiveColor : self.attackingColor }, { duration: 200 }); } }); } } } if (self.copiedSpeedBurst) { // Update Speed Burst cooldown if (self.copiedSpeedBurstCooldown > 0) { self.copiedSpeedBurstCooldown -= 16; if (self.copiedSpeedBurstCooldown < 0) self.copiedSpeedBurstCooldown = 0; } // Speed burst when close to ball if (!self.copiedSpeedBurstActive && self.copiedSpeedBurstCooldown <= 0 && distance < 100) { self.copiedSpeedBurstActive = true; self.copiedSpeedBurstCooldown = 8000; // 8 seconds cooldown self.speed = self.copiedBurstSpeed; // Visual effect for speed burst tween(self, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 100 }); } }); // Speed burst lasts for 2 seconds LK.setTimeout(function () { self.copiedSpeedBurstActive = false; self.speed = self.copiedNormalSpeed; }, 2000); } } var dx = ball.x - self.x; var dy = ball.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // Mode-based behavior if (self.isDefensiveMode) { // Defensive mode: stay back and intercept if (distance < 300) { var defensiveSpeed = self.speed * 0.8; self.x += dx / distance * defensiveSpeed; self.y += dy / distance * defensiveSpeed; // Defensive tackle if (distance < 80) { var clearX = ball.x < 1024 ? ball.x - 300 : ball.x + 300; var clearY = ball.y - 200; var clearDx = clearX - ball.x; var clearDy = clearY - ball.y; var clearDist = Math.sqrt(clearDx * clearDx + clearDy * clearDy); if (clearDist > 0) { ball.velocityX = clearDx / clearDist * 8; ball.velocityY = clearDy / clearDist * 8; } } } else { // Return to defensive position var homeDx = self.homeX - self.x; var homeDy = self.homeY - self.y; var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy); if (homeDistance > 50) { self.x += homeDx / homeDistance * self.speed * 0.5; self.y += homeDy / homeDistance * self.speed * 0.5; } } } else { // Attacking mode: chase ball aggressively if (distance < 400) { var attackSpeed = self.speed * 1.3; self.x += dx / distance * attackSpeed; self.y += dy / distance * attackSpeed; // Attack shot if (distance < 80) { var goalDx = opponentGoal.x - ball.x; var goalDy = opponentGoal.y - ball.y; var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy); if (goalDistance > 0) { ball.velocityX = goalDx / goalDistance * 12; ball.velocityY = goalDy / goalDistance * 12; } } } } }; self.activateChameleon = function () { // Find random NPC to copy stats from (including player team members) var availableNPCs = []; for (var i = 0; i < opponents.length; i++) { availableNPCs.push(opponents[i]); } // Also add player team members with special abilities if (typeof hiori !== 'undefined') availableNPCs.push(hiori); if (typeof chigiri !== 'undefined') availableNPCs.push(chigiri); if (availableNPCs.length > 0) { var randomNPC = availableNPCs[Math.floor(Math.random() * availableNPCs.length)]; // Copy stats from random NPC self.copiedStats = { speed: randomNPC.speed || self.originalSpeed, dribbling: randomNPC.dribbleSpeed || self.originalDribbling, shot: randomNPC.burstSpeed || self.originalShot, role: randomNPC.role || 'reo' }; // Apply copied stats self.speed = self.copiedStats.speed; // Copy special abilities based on role if (self.copiedStats.role === 'hiori') { // Copy Winter Zone ability self.copiedWinterZone = true; self.copiedWinterZoneRadius = 200; self.copiedWinterZoneCooldown = 0; self.copiedWinterZoneActive = false; self.copiedWinterZoneDuration = 0; self.copiedWinterZoneMaxDuration = 8000; // Slightly shorter than original self.copiedSlowedOpponents = []; self.copiedWinterZoneVisual = null; } else if (self.copiedStats.role === 'chigiri') { // Copy Speed Burst ability self.copiedSpeedBurst = true; self.copiedSpeedBurstCooldown = 0; self.copiedSpeedBurstActive = false; self.copiedBurstSpeed = 10; self.copiedNormalSpeed = self.speed; } else { // Reset copied abilities self.copiedWinterZone = false; self.copiedSpeedBurst = false; } // Visual effect for Chameleon activation tween(self, { scaleX: 1.3, scaleY: 1.3, tint: 0xff00ff }, { duration: 200, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1, tint: self.isDefensiveMode ? self.defensiveColor : self.attackingColor }, { duration: 200 }); } }); } }; return self; }); var SoccerBall = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.friction = 0.98; self.active = true; self.update = function () { if (self.active) { self.x += self.velocityX; self.y += self.velocityY; self.velocityX *= self.friction; self.velocityY *= self.friction; // Keep ball in bounds with bounce effect if (self.x < 30) { self.x = 30; self.velocityX = Math.abs(self.velocityX) * 0.8; } if (self.x > 2018) { self.x = 2018; self.velocityX = -Math.abs(self.velocityX) * 0.8; } if (self.y < 30) { self.y = 30; self.velocityY = Math.abs(self.velocityY) * 0.8; } if (self.y > 2702) { self.y = 2702; self.velocityY = -Math.abs(self.velocityY) * 0.8; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x228B22 }); /**** * Game Code ****/ game.setBackgroundColor(0x228B22); // Game variables var opponents = []; var playerScore = 0; var opponentScore = 0; var dragNode = null; var maxStamina = 100; var currentStamina = 100; var staminaRegenRate = 0.2; var staminaDrainRate = 0.5; var lastPlayerX = 0; var lastPlayerY = 0; var shotChargeStart = 0; var isChargingShot = false; var shotPower = 0; var maxShotPower = 20; var minChargeTime = 2000; // 2 seconds minimum charge time var lastTouchX = 0; var lastTouchY = 0; var ballDetachCooldown = 0; var ballDetachCooldownTime = 1000; // 1 second cooldown // UI Elements var scoreTxt = new Text2('Player: 0 - Opponent: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Stamina UI var staminaTxt = new Text2('Stamina: 100', { size: 60, fill: 0x00FF00 }); staminaTxt.anchor.set(0, 0); staminaTxt.x = 50; staminaTxt.y = 50; LK.gui.topLeft.addChild(staminaTxt); // Shot Power UI var shotPowerTxt = new Text2('Shot Power: 0%', { size: 60, fill: 0xFFFFFF }); shotPowerTxt.anchor.set(0, 0); shotPowerTxt.x = 50; shotPowerTxt.y = 130; LK.gui.topLeft.addChild(shotPowerTxt); // Game objects var player = game.addChild(new Player()); player.x = 1024; player.y = 2200; var ball = game.addChild(new SoccerBall()); ball.x = 1024; ball.y = 1366; // Player's goal (bottom) var playerGoal = game.addChild(new Goal()); playerGoal.x = 1024; playerGoal.y = 2600; // Opponent's goal (top) var opponentGoal = game.addChild(new Goal()); opponentGoal.x = 1024; opponentGoal.y = 300; // Create opponents with specific roles // Defense player (opponent) var defensePlayer = game.addChild(new DefensePlayer()); defensePlayer.x = 1024; defensePlayer.y = 600; defensePlayer.homeX = 1024; defensePlayer.homeY = 600; opponents.push(defensePlayer); // Chigiri - player team hybrid defender var chigiri = game.addChild(new ChigiriPlayer(0x3399ff)); chigiri.x = 800; chigiri.y = 2000; chigiri.homeX = 800; chigiri.homeY = 2000; // Hiori - player team creative midfielder var hiori = game.addChild(new HioriPlayer(0x6699ff)); hiori.x = 1200; hiori.y = 2000; hiori.homeX = 1200; hiori.homeY = 2000; // Reo - player team adaptive defender/attacker var reo = game.addChild(new ReoPlayer(0x000000)); reo.x = 600; reo.y = 1800; reo.homeX = 600; reo.homeY = 1800; // Midfield player var midfieldPlayer = game.addChild(new MidfieldPlayer()); midfieldPlayer.x = 1024; midfieldPlayer.y = 1000; midfieldPlayer.homeX = 1024; midfieldPlayer.homeY = 1000; opponents.push(midfieldPlayer); // Forward player var forwardPlayer = game.addChild(new ForwardPlayer()); forwardPlayer.x = 1024; forwardPlayer.y = 1400; forwardPlayer.homeX = 1024; forwardPlayer.homeY = 1400; opponents.push(forwardPlayer); // Create goalkeepers var playerGoalkeeper = game.addChild(new Goalkeeper(true)); // Blue goalkeeper for player team playerGoalkeeper.x = 1024; playerGoalkeeper.y = 2500; // In front of player's goal playerGoalkeeper.originalX = 1024; playerGoalkeeper.originalY = 2500; var opponentGoalkeeper = game.addChild(new Goalkeeper(false)); // Red goalkeeper for opponent team opponentGoalkeeper.x = 1024; opponentGoalkeeper.y = 400; // In front of opponent's goal opponentGoalkeeper.originalX = 1024; opponentGoalkeeper.originalY = 400; // Ball kicking mechanics function kickBall(targetX, targetY, power) { var dx = targetX - ball.x; var dy = targetY - ball.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { var finalPower = power || Math.min(distance / 100, 15); // Properly detach ball from player first player.hasBall = false; ball.active = true; // Set cooldown to prevent immediate re-attachment ballDetachCooldown = ballDetachCooldownTime; // Apply velocity after detachment ball.velocityX = dx / distance * finalPower; ball.velocityY = dy / distance * finalPower; LK.getSound('kick').play(); } } // Touch controls for player movement and ball kicking game.down = function (x, y, obj) { // Always update last touch position for shot direction lastTouchX = x; lastTouchY = y; var playerDistance = Math.sqrt((x - player.x) * (x - player.x) + (y - player.y) * (y - player.y)); var ballDistance = Math.sqrt((x - ball.x) * (x - ball.x) + (y - ball.y) * (y - ball.y)); if (playerDistance < ballDistance) { // Move player dragNode = player; } else { // Start charging shot if player has ball if (player.hasBall) { shotChargeStart = Date.now(); isChargingShot = true; shotPower = 0; } } }; game.move = function (x, y, obj) { // Always update last touch position for shot direction lastTouchX = x; lastTouchY = y; if (dragNode && currentStamina > 0) { var dx = x - dragNode.x; var dy = y - dragNode.y; var distance = Math.sqrt(dx * dx + dy * dy); // Slow down movement and consume stamina - even slower when having ball var moveSpeed = player.hasBall ? 0.15 : 0.2; dragNode.x += dx * moveSpeed; dragNode.y += dy * moveSpeed; // Consume stamina based on movement if (distance > 5) { currentStamina -= staminaDrainRate; if (currentStamina < 0) currentStamina = 0; } } }; game.up = function (x, y, obj) { dragNode = null; // Handle shot release if (isChargingShot && player.hasBall) { var chargeTime = Date.now() - shotChargeStart; if (chargeTime >= minChargeTime) { // Release charged shot - use last touch position for direction kickBall(lastTouchX, lastTouchY, shotPower); } else { // Not charged enough, no shot } isChargingShot = false; shotPower = 0; } }; // Goal scoring function function scoreGoal(isPlayer) { if (isPlayer) { playerScore++; } else { opponentScore++; } scoreTxt.setText('Player: ' + playerScore + ' - Opponent: ' + opponentScore); LK.getSound('goal').play(); // Reset ball position ball.x = 1024; ball.y = 1366; ball.velocityX = 0; ball.velocityY = 0; } // Game update loop game.update = function () { // Update ball detach cooldown if (ballDetachCooldown > 0) { ballDetachCooldown -= 16; // Approximately 60 FPS if (ballDetachCooldown < 0) ballDetachCooldown = 0; } // Check if player is close to ball for interaction (only if cooldown expired) var playerToBallDistance = Math.sqrt((player.x - ball.x) * (player.x - ball.x) + (player.y - ball.y) * (player.y - ball.y)); if (playerToBallDistance < 80 && !player.hasBall && ballDetachCooldown <= 0) { player.hasBall = true; ball.active = false; ball.velocityX = 0; ball.velocityY = 0; } // If player has ball, make it stick to player if (player.hasBall && ball.active === false) { ball.x = player.x; ball.y = player.y - 50; } // Stamina regeneration when not moving var playerMoving = Math.abs(player.x - lastPlayerX) > 1 || Math.abs(player.y - lastPlayerY) > 1; if (!playerMoving && currentStamina < maxStamina) { currentStamina += staminaRegenRate; if (currentStamina > maxStamina) currentStamina = maxStamina; } // Update last position lastPlayerX = player.x; lastPlayerY = player.y; // Update stamina UI var staminaPercent = Math.round(currentStamina / maxStamina * 100); staminaTxt.setText('Stamina: ' + staminaPercent); // Change color based on stamina level if (staminaPercent > 50) { staminaTxt.fill = 0x00FF00; } else if (staminaPercent > 25) { staminaTxt.fill = 0xFFFF00; } else { staminaTxt.fill = 0xFF0000; } // Update shot charging if (isChargingShot && player.hasBall) { var chargeTime = Date.now() - shotChargeStart; if (chargeTime >= minChargeTime) { // Calculate shot power based on charge time var chargeProgress = Math.min((chargeTime - minChargeTime) / 1000, 1); // 1 second after minimum for max power shotPower = 5 + chargeProgress * maxShotPower; // Minimum 5, maximum 25 power var powerPercent = Math.round(chargeProgress * 100); shotPowerTxt.setText('Shot Power: ' + powerPercent + '%'); shotPowerTxt.fill = 0x00FF00; // Automatically kick ball forward when shot power reaches 100% if (powerPercent >= 100) { shotPower = 5 + maxShotPower; // Keep at maximum power shotPowerTxt.setText('Shot Power: 100%'); shotPowerTxt.fill = 0x00FF00; // Auto-kick ball forward when power reaches 100% var forwardX = player.x; var forwardY = player.y - 300; // Kick forward (up the field) kickBall(forwardX, forwardY, shotPower); isChargingShot = false; shotPower = 0; } } else { // Not charged enough yet var timeLeft = Math.ceil((minChargeTime - chargeTime) / 1000); shotPowerTxt.setText('Hold for ' + timeLeft + 's'); shotPowerTxt.fill = 0xFFFF00; } } else { shotPowerTxt.setText('Shot Power: 0%'); shotPowerTxt.fill = 0xFFFFFF; } // Check player goal scoring (opponent scores) if (ball.y > playerGoal.y - 50 && ball.x > playerGoal.x - 200 && ball.x < playerGoal.x + 200) { scoreGoal(false); LK.effects.flashObject(playerGoal, 0xFF0000, 500); } // Check opponent goal scoring (player scores) if (ball.y < opponentGoal.y + 50 && ball.x > opponentGoal.x - 200 && ball.x < opponentGoal.x + 200) { scoreGoal(true); LK.effects.flashObject(opponentGoal, 0x00FF00, 500); } // Check win condition if (playerScore >= 5) { LK.showYouWin(); } if (opponentScore >= 5) { LK.showGameOver(); } // Enhanced AI positioning based on ball location for (var i = 0; i < opponents.length; i++) { var opponent = opponents[i]; var ballThreatLevel = Math.sqrt((ball.x - 1024) * (ball.x - 1024) + (ball.y - 1366) * (ball.y - 1366)); // Adjust opponent aggression based on ball threat if (ballThreatLevel < 300) { // Ball is in center - all opponents become more aggressive if (opponent.role === 'defense') { opponent.speed = 4.5; opponent.maxDistance = 500; } else if (opponent.role === 'midfield') { opponent.speed = 3.5; } else if (opponent.role === 'forward') { opponent.speed = 4.2; } } else { // Ball is far - return to normal behavior if (opponent.role === 'defense') { opponent.speed = 4; opponent.maxDistance = 400; } else if (opponent.role === 'midfield') { opponent.speed = 3; } else if (opponent.role === 'forward') { opponent.speed = 3.5; } } } // Role-based AI is now handled in each player's update method // Defense, Midfield, and Forward players have their own specialized behaviors };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ChigiriPlayer = Container.expand(function (colorOverride) {
var self = Container.call(this);
var opponentGraphics = self.attachAsset('opponent', {
anchorX: 0.5,
anchorY: 0.5
});
if (typeof colorOverride === "number" && opponentGraphics) {
opponentGraphics.tint = colorOverride;
}
self.speed = 5;
self.role = 'chigiri';
self.homeX = 800;
self.homeY = 2000;
self.maxDistance = 600;
self.hasBall = false;
self.isSpeedBursting = false;
self.speedBurstTarget = null;
self.speedBurstCooldown = 0;
self.speedBurstCooldownTime = 8000; // 8 seconds
self.normalSpeed = 5;
self.burstSpeed = 12;
self.update = function () {
// Update speed burst cooldown
if (self.speedBurstCooldown > 0) {
self.speedBurstCooldown -= 16;
if (self.speedBurstCooldown < 0) self.speedBurstCooldown = 0;
}
// Steal ball if opponent is inside area
var nearestOpponent = null;
var nearestDistance = Infinity;
for (var i = 0; i < opponents.length; i++) {
var opponentDist = Math.sqrt((opponents[i].x - self.x) * (opponents[i].x - self.x) + (opponents[i].y - self.y) * (opponents[i].y - self.y));
if (opponentDist < nearestDistance) {
nearestDistance = opponentDist;
nearestOpponent = opponents[i];
}
}
if (nearestOpponent && nearestDistance < 80 && nearestOpponent.hasBall) {
// Steal the ball
nearestOpponent.hasBall = false;
ball.active = true;
// Ball moves toward Chigiri
var stealDx = self.x - nearestOpponent.x;
var stealDy = self.y - nearestOpponent.y;
var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy);
if (stealDist > 0) {
ball.velocityX = stealDx / stealDist * 8;
ball.velocityY = stealDy / stealDist * 8;
}
ballDetachCooldown = ballDetachCooldownTime;
}
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Enhanced ball pursuit for hybrid player
if (distance < 500 && !self.isSpeedBursting) {
// Chase ball with hybrid intelligence
var chaseSpeed = distance < 150 ? self.normalSpeed * 1.4 : self.normalSpeed * 1.1;
self.x += dx / distance * chaseSpeed;
self.y += dy / distance * chaseSpeed;
}
// Speed burst mechanic
if (!self.isSpeedBursting && self.speedBurstCooldown <= 0 && distance < 100) {
// Throw ball forward and start speed burst
var throwX = opponentGoal.x + (Math.random() - 0.5) * 200;
var throwY = opponentGoal.y + 200;
var throwDx = throwX - ball.x;
var throwDy = throwY - ball.y;
var throwDist = Math.sqrt(throwDx * throwDx + throwDy * throwDy);
if (throwDist > 0) {
ball.velocityX = throwDx / throwDist * 14;
ball.velocityY = throwDy / throwDist * 14;
}
// Set speed burst target and activate
self.speedBurstTarget = {
x: throwX,
y: throwY
};
self.isSpeedBursting = true;
self.speedBurstCooldown = self.speedBurstCooldownTime; // Start cooldown
// Visual effect for speed burst
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
}
if (self.isSpeedBursting && self.speedBurstTarget) {
// Move at burst speed toward target
var burstDx = self.speedBurstTarget.x - self.x;
var burstDy = self.speedBurstTarget.y - self.y;
var burstDist = Math.sqrt(burstDx * burstDx + burstDy * burstDy);
if (burstDist > 30) {
self.x += burstDx / burstDist * self.burstSpeed;
self.y += burstDy / burstDist * self.burstSpeed;
} else {
// Reached target, stop speed burst
self.isSpeedBursting = false;
self.speedBurstTarget = null;
}
} else {
// Normal hybrid behavior - enhanced ball pursuit
if (distance < 500) {
// Move toward ball with improved midfielder intelligence
var pursuitSpeed = distance < 200 ? self.normalSpeed * 1.3 : self.normalSpeed * 1.1;
self.x += dx / distance * pursuitSpeed;
self.y += dy / distance * pursuitSpeed;
// Attack opponent goal if close to ball
if (distance < 80) {
var goalDx = opponentGoal.x - ball.x;
var goalDy = opponentGoal.y - ball.y;
var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy);
if (goalDistance > 0) {
ball.velocityX = goalDx / goalDistance * 11;
ball.velocityY = goalDy / goalDistance * 11;
}
}
} else {
// Return to defensive position
var homeDx = self.homeX - self.x;
var homeDy = self.homeY - self.y;
var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy);
if (homeDistance > 50) {
self.x += homeDx / homeDistance * self.normalSpeed * 0.4;
self.y += homeDy / homeDistance * self.normalSpeed * 0.4;
}
}
}
};
return self;
});
var DefensePlayer = Container.expand(function (colorOverride) {
var self = Container.call(this);
var opponentGraphics = self.attachAsset('opponent', {
anchorX: 0.5,
anchorY: 0.5
});
if (typeof colorOverride === "number" && opponentGraphics) {
opponentGraphics.tint = colorOverride;
}
self.speed = 4;
self.role = 'defense';
self.homeX = 1024;
self.homeY = 600;
self.maxDistance = 400;
self.hasBall = false;
self.update = function () {
// Steal ball if player is inside opponent
var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (playerDist < 80 && player.hasBall) {
// Steal the ball
player.hasBall = false;
ball.active = true;
// Ball moves away from player, toward defense
var stealDx = self.x - player.x;
var stealDy = self.y - player.y;
var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy);
if (stealDist > 0) {
ball.velocityX = stealDx / stealDist * 10;
ball.velocityY = stealDy / stealDist * 10;
}
// Prevent immediate re-attachment
ballDetachCooldown = ballDetachCooldownTime;
}
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Defense priority: desperately try to get the ball
if (distance < 400) {
// Move aggressively toward ball - increased chase range
self.x += dx / distance * (self.speed * 1.2);
self.y += dy / distance * (self.speed * 1.2);
// Sliding tackle if player is close to defense
var playerDistance = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (playerDistance < 120 && ball.active && !player.hasBall) {
// Slide tackle: dash toward ball and clear it away
var slideDx = ball.x - self.x;
var slideDy = ball.y - self.y;
var slideDist = Math.sqrt(slideDx * slideDx + slideDy * slideDy);
if (slideDist > 0) {
// Animate slide (quick move)
tween(self, {
x: self.x + slideDx / slideDist * 60,
y: self.y + slideDy / slideDist * 60
}, {
duration: 120,
easing: tween.cubicOut
});
// Clear ball far away from player
var clearX = ball.x < 1024 ? ball.x - 400 : ball.x + 400;
var clearY = ball.y - 500;
var clearDx = clearX - ball.x;
var clearDy = clearY - ball.y;
var clearDist = Math.sqrt(clearDx * clearDx + clearDy * clearDy);
if (clearDist > 0) {
ball.velocityX = clearDx / clearDist * 13;
ball.velocityY = clearDy / clearDist * 13;
}
}
}
// Kick ball away from player goal if close enough
if (distance < 80) {
// Find nearest forward player
var nearestForward = null;
var nearestDistance = Infinity;
for (var i = 0; i < opponents.length; i++) {
if (opponents[i].role === 'forward') {
var forwardDx = opponents[i].x - self.x;
var forwardDy = opponents[i].y - self.y;
var forwardDistance = Math.sqrt(forwardDx * forwardDx + forwardDy * forwardDy);
if (forwardDistance < nearestDistance) {
nearestDistance = forwardDistance;
nearestForward = opponents[i];
}
}
}
// Pass to forward if found, otherwise clear as before
if (nearestForward) {
var passDx = nearestForward.x - ball.x;
var passDy = nearestForward.y - ball.y;
var passDistance = Math.sqrt(passDx * passDx + passDy * passDy);
if (passDistance > 0) {
ball.velocityX = passDx / passDistance * 10;
ball.velocityY = passDy / passDistance * 10;
}
} else {
var kickAwayX = ball.x < 1024 ? ball.x - 200 : ball.x + 200;
var kickAwayY = ball.y - 300; // Kick upfield
var kickDx = kickAwayX - ball.x;
var kickDy = kickAwayY - ball.y;
var kickDistance = Math.sqrt(kickDx * kickDx + kickDy * kickDy);
if (kickDistance > 0) {
ball.velocityX = kickDx / kickDistance * 8;
ball.velocityY = kickDy / kickDistance * 8;
}
}
}
} else {
// Return to defensive position
var homeDx = self.homeX - self.x;
var homeDy = self.homeY - self.y;
var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy);
if (homeDistance > 50) {
self.x += homeDx / homeDistance * self.speed * 0.5;
self.y += homeDy / homeDistance * self.speed * 0.5;
}
}
};
return self;
});
var ForwardPlayer = Container.expand(function () {
var self = Container.call(this);
var opponentGraphics = self.attachAsset('opponent', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3.5;
self.role = 'forward';
self.homeX = 1024;
self.homeY = 1400;
self.hasBall = false;
self.directShotCooldown = self.directShotCooldown || 0;
self.update = function () {
// Steal ball if player is inside opponent
var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (playerDist < 80 && player.hasBall) {
// Steal the ball
player.hasBall = false;
ball.active = true;
// Ball moves away from player, toward forward
var stealDx = self.x - player.x;
var stealDy = self.y - player.y;
var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy);
if (stealDist > 0) {
ball.velocityX = stealDx / stealDist * 10;
ball.velocityY = stealDy / stealDist * 10;
}
// Prevent immediate re-attachment
ballDetachCooldown = ballDetachCooldownTime;
}
// Handle direct shot cooldown
if (self.directShotCooldown > 0) {
self.directShotCooldown -= 16;
if (self.directShotCooldown < 0) self.directShotCooldown = 0;
}
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Forward: attack and try to score
if (distance < 400) {
// Move toward ball with aggressive pursuit
var pursuitSpeed = distance < 200 ? self.speed * 1.8 : self.speed * 1.3;
self.x += dx / distance * pursuitSpeed;
self.y += dy / distance * pursuitSpeed;
// If close to ball, shoot at goal
if (distance < 80) {
// Direct Shot every 30s
if (self.directShotCooldown <= 0) {
var goalDx = playerGoal.x - ball.x;
var goalDy = playerGoal.y - ball.y;
var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy);
if (goalDistance > 0) {
// Direct Shot: very fast and straight
ball.velocityX = goalDx / goalDistance * 18;
ball.velocityY = goalDy / goalDistance * 18;
}
self.directShotCooldown = 30000; // 30 seconds
} else {
// Normal shot
var goalDx = playerGoal.x - ball.x;
var goalDy = playerGoal.y - ball.y;
var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy);
if (goalDistance > 0) {
ball.velocityX = goalDx / goalDistance * 10;
ball.velocityY = goalDy / goalDistance * 10;
}
}
}
} else {
// Move toward attacking position
var homeDx = self.homeX - self.x;
var homeDy = self.homeY - self.y;
var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy);
if (homeDistance > 50) {
self.x += homeDx / homeDistance * self.speed * 0.4;
self.y += homeDy / homeDistance * self.speed * 0.4;
}
}
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
// Goal area
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
goalGraphics.alpha = 0.3;
// Left goalpost
var leftPost = self.addChild(LK.getAsset('goalpost', {
anchorX: 0.5,
anchorY: 0.5
}));
leftPost.x = -210;
leftPost.y = 0;
// Right goalpost
var rightPost = self.addChild(LK.getAsset('goalpost', {
anchorX: 0.5,
anchorY: 0.5
}));
rightPost.x = 210;
rightPost.y = 0;
return self;
});
var Goalkeeper = Container.expand(function (isPlayer) {
var self = Container.call(this);
var keeperGraphics = self.attachAsset(isPlayer ? 'player' : 'opponent', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.isPlayer = isPlayer;
self.rushCooldown = 0;
self.rushCooldownTime = 20000; // 20 seconds
self.isRushing = false;
self.originalX = 0;
self.originalY = 0;
self.rushSpeed = 8;
self.update = function () {
// Update rush cooldown
if (self.rushCooldown > 0) {
self.rushCooldown -= 16; // Approximately 60 FPS
if (self.rushCooldown < 0) self.rushCooldown = 0;
}
// Check if should rush for ball
var ballDistance = Math.sqrt((ball.x - self.x) * (ball.x - self.x) + (ball.y - self.y) * (ball.y - self.y));
if (!self.isRushing && self.rushCooldown <= 0 && ballDistance < 400) {
// Start rushing
self.isRushing = true;
self.rushCooldown = self.rushCooldownTime;
}
if (self.isRushing) {
// Rush toward ball
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0 && distance > 50) {
self.x += dx / distance * self.rushSpeed;
self.y += dy / distance * self.rushSpeed;
} else if (distance <= 50) {
// Catch ball if close enough
ball.velocityX = 0;
ball.velocityY = 0;
ball.x = self.x;
ball.y = self.y;
ball.active = false;
player.hasBall = false;
// Return to original position first
self.isRushing = false;
tween(self, {
x: self.originalX,
y: self.originalY
}, {
duration: 1000,
onFinish: function onFinish() {
// After returning to position, throw ball to center field
ball.active = true;
var centerX = 1024;
var centerY = 1366;
var throwPower = 15;
var throwDx = centerX - ball.x;
var throwDy = centerY - ball.y;
var throwDistance = Math.sqrt(throwDx * throwDx + throwDy * throwDy);
if (throwDistance > 0) {
ball.velocityX = throwDx / throwDistance * throwPower;
ball.velocityY = throwDy / throwDistance * throwPower;
}
}
});
}
} else {
// Normal goalkeeper movement - stay near goal line
var goalCenterX = 1024;
var dx = goalCenterX - self.x;
if (Math.abs(dx) > 5) {
self.x += dx > 0 ? self.speed : -self.speed;
}
}
};
return self;
});
var HioriPlayer = Container.expand(function (colorOverride) {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
if (typeof colorOverride === "number" && playerGraphics) {
playerGraphics.tint = colorOverride;
}
self.speed = 4;
self.role = 'hiori';
self.homeX = 1200;
self.homeY = 2000;
self.hasBall = false;
// Zig-zag dribbling variables
self.isDribbling = false;
self.dribbleStartTime = 0;
self.dribbleDuration = 2000; // 2 seconds - slower duration
self.dribbleSpeed = 6;
self.dribbleDirection = 1; // 1 for right, -1 for left
self.dribblePhase = 0; // 0-1 progress through dribble
self.dribbleStartX = 0;
self.dribbleStartY = 0;
self.dribbleTargetX = 0;
self.dribbleTargetY = 0;
// Zigzag pause variables
self.zigzagCount = 0;
self.zigzagPaused = false;
self.zigzagPauseStart = 0;
self.zigzagPauseDuration = 10000; // 10 seconds
// Winter Zone variables
self.winterZoneActive = false;
self.winterZoneRadius = 200;
self.winterZoneCooldown = 0;
self.winterZoneCooldownTime = 12000; // 12 seconds
self.winterZoneDuration = 0;
self.winterZoneMaxDuration = 10000; // 10 seconds - increased duration
self.slowedOpponents = [];
// Winter Zone visual
self.winterZoneVisual = null;
// Perfect pass variables
self.passChargingTime = 0;
self.perfectPassCooldown = 0;
self.perfectPassCooldownTime = 6000; // 6 seconds
self.update = function () {
// Update cooldowns
if (self.winterZoneCooldown > 0) {
self.winterZoneCooldown -= 16;
if (self.winterZoneCooldown < 0) self.winterZoneCooldown = 0;
}
if (self.perfectPassCooldown > 0) {
self.perfectPassCooldown -= 16;
if (self.perfectPassCooldown < 0) self.perfectPassCooldown = 0;
}
// Winter Zone duration and effect
if (self.winterZoneActive) {
self.winterZoneDuration -= 16;
if (self.winterZoneDuration <= 0) {
self.winterZoneActive = false;
// Remove Winter Zone visual
if (self.winterZoneVisual) {
self.winterZoneVisual.destroy();
self.winterZoneVisual = null;
}
// Restore opponent speeds
for (var i = 0; i < self.slowedOpponents.length; i++) {
var opponent = self.slowedOpponents[i];
opponent.speed = opponent.originalSpeed || opponent.speed * 2;
}
self.slowedOpponents = [];
} else {
// Apply Winter Zone effect to nearby opponents
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y));
if (dist <= self.winterZoneRadius) {
if (self.slowedOpponents.indexOf(opponent) === -1) {
opponent.originalSpeed = opponent.speed;
opponent.speed = opponent.speed * 0.3; // Slow to 30% speed
self.slowedOpponents.push(opponent);
}
}
}
}
}
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Zig-zag dribbling logic
if (self.isDribbling) {
var elapsed = Date.now() - self.dribbleStartTime;
var progress = Math.min(elapsed / self.dribbleDuration, 1);
// Create zig-zag pattern - slower frequency for better visibility
var zigzagAmplitude = 80;
var zigzagFrequency = 4;
var zigzagOffset = Math.sin(progress * Math.PI * zigzagFrequency) * zigzagAmplitude;
// Move toward target with zig-zag motion - slower speed
var targetDx = self.dribbleTargetX - self.dribbleStartX;
var targetDy = self.dribbleTargetY - self.dribbleStartY;
var targetDist = Math.sqrt(targetDx * targetDx + targetDy * targetDy);
if (targetDist > 0) {
// Calculate perpendicular vector for zig-zag
var perpX = -targetDy / targetDist;
var perpY = targetDx / targetDist;
// Apply zig-zag movement with slower speed
var slowSpeed = 0.6; // Reduced from 1.0 to make it slower
self.x = self.dribbleStartX + targetDx * progress * slowSpeed + perpX * zigzagOffset;
self.y = self.dribbleStartY + targetDy * progress * slowSpeed + perpY * zigzagOffset;
// Ball follows during dribble
if (distance < 100) {
ball.x = self.x;
ball.y = self.y;
ball.velocityX = 0;
ball.velocityY = 0;
}
}
// End dribbling
if (progress >= 1) {
self.isDribbling = false;
self.zigzagCount = (self.zigzagCount || 0) + 1;
// After 4 zigzags, pause for 10 seconds
if (self.zigzagCount >= 4) {
self.zigzagPaused = true;
self.zigzagPauseStart = Date.now();
self.zigzagCount = 0;
}
}
} else {
// Normal ball pursuit
if (distance < 400) {
var chaseSpeed = distance < 150 ? self.speed * 1.3 : self.speed * 1.1;
self.x += dx / distance * chaseSpeed;
self.y += dy / distance * chaseSpeed;
// Handle zigzag pause
if (self.zigzagPaused) {
var pauseElapsed = Date.now() - self.zigzagPauseStart;
if (pauseElapsed >= self.zigzagPauseDuration) {
self.zigzagPaused = false;
}
}
// Start zig-zag dribbling when close to ball (only if not paused)
if (distance < 80 && !self.isDribbling && !self.zigzagPaused) {
self.isDribbling = true;
self.dribbleStartTime = Date.now();
self.dribbleStartX = self.x;
self.dribbleStartY = self.y;
// Dribble toward opponent goal
self.dribbleTargetX = opponentGoal.x + (Math.random() - 0.5) * 300;
self.dribbleTargetY = opponentGoal.y + 200;
}
}
}
// Activate Winter Zone when opponents get close
if (!self.winterZoneActive && self.winterZoneCooldown <= 0) {
var nearbyOpponents = 0;
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y));
if (dist <= self.winterZoneRadius + 50) {
nearbyOpponents++;
}
}
if (nearbyOpponents >= 2) {
// Activate Winter Zone
self.winterZoneActive = true;
self.winterZoneDuration = self.winterZoneMaxDuration;
self.winterZoneCooldown = self.winterZoneCooldownTime;
// Create Winter Zone visual area
self.winterZoneVisual = self.addChild(LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
tint: 0x87CEEB
}));
self.winterZoneVisual.alpha = 0.3;
// Visual effect
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x87CEEB
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
}
}
// Perfect deceptive pass when close to ball
if (distance < 80 && self.perfectPassCooldown <= 0) {
// Look for player to pass to
var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (playerDist < 600 && playerDist > 100) {
// Execute perfect deceptive pass
var passDx = player.x - ball.x;
var passDy = player.y - ball.y;
var passDist = Math.sqrt(passDx * passDx + passDy * passDy);
if (passDist > 0) {
// Perfect pass with slight curve to avoid interception
var curveAmount = 3;
ball.velocityX = passDx / passDist * 12 + curveAmount;
ball.velocityY = passDy / passDist * 12;
ball.active = true;
self.perfectPassCooldown = self.perfectPassCooldownTime;
// Visual effect for perfect pass
tween(ball, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 150,
onFinish: function onFinish() {
tween(ball, {
scaleX: 1,
scaleY: 1
}, {
duration: 150
});
}
});
}
}
}
// Return to home position when not actively playing
if (distance > 500) {
var homeDx = self.homeX - self.x;
var homeDy = self.homeY - self.y;
var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy);
if (homeDistance > 50) {
self.x += homeDx / homeDistance * self.speed * 0.4;
self.y += homeDy / homeDistance * self.speed * 0.4;
}
}
};
return self;
});
var MidfieldPlayer = Container.expand(function () {
var self = Container.call(this);
var opponentGraphics = self.attachAsset('opponent', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.role = 'midfield';
self.homeX = 1024;
self.homeY = 1000;
self.hasBall = false;
// Dribbling state
self.isDribbling = false;
self.dribbleStartTime = 0;
self.dribbleDuration = 1000;
self.dribbleRadius = 120;
self.dribbleStartAngle = 0;
self.dribbleEndAngle = 0;
self.dribbleOriginX = 0;
self.dribbleOriginY = 0;
self.hasDribbled = false;
self.update = function () {
// Steal ball if player is inside opponent
var playerDist = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (playerDist < 80 && player.hasBall) {
// Steal the ball
player.hasBall = false;
ball.active = true;
// Ball moves away from player, toward midfield
var stealDx = self.x - player.x;
var stealDy = self.y - player.y;
var stealDist = Math.sqrt(stealDx * stealDx + stealDy * stealDy);
if (stealDist > 0) {
ball.velocityX = stealDx / stealDist * 10;
ball.velocityY = stealDy / stealDist * 10;
}
// Prevent immediate re-attachment
ballDetachCooldown = ballDetachCooldownTime;
}
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Midfield: get ball and pass to forward
if (distance < 350) {
// Move toward ball with increased speed when chasing
var chaseSpeed = distance < 150 ? self.speed * 1.5 : self.speed * 1.2;
self.x += dx / distance * chaseSpeed;
self.y += dy / distance * chaseSpeed;
// If close to ball, run away from player and pass to forward
if (distance < 80) {
// Move away from player for a moment
var awayDx = self.x - player.x;
var awayDy = self.y - player.y;
var awayDist = Math.sqrt(awayDx * awayDx + awayDy * awayDy);
if (awayDist > 0) {
tween(self, {
x: self.x + awayDx / awayDist * 120,
y: self.y + awayDy / awayDist * 120
}, {
duration: 200,
easing: tween.cubicOut
});
}
// Find nearest forward player
var nearestForward = null;
var nearestDistance = Infinity;
for (var i = 0; i < opponents.length; i++) {
if (opponents[i].role === 'forward') {
var forwardDx = opponents[i].x - self.x;
var forwardDy = opponents[i].y - self.y;
var forwardDistance = Math.sqrt(forwardDx * forwardDx + forwardDy * forwardDy);
if (forwardDistance < nearestDistance) {
nearestDistance = forwardDistance;
nearestForward = opponents[i];
}
}
}
// Pass to forward if found
if (nearestForward) {
// Perfect pass: ball goes directly to forward with good speed
var passDx = nearestForward.x - ball.x;
var passDy = nearestForward.y - ball.y;
var passDistance = Math.sqrt(passDx * passDx + passDy * passDy);
if (passDistance > 0) {
ball.velocityX = passDx / passDistance * 10;
ball.velocityY = passDy / passDistance * 10;
}
} else {
// No forward to pass to: perform dribbling and curved shot
if (!self.isDribbling) {
// Start dribbling: move in a half-circle around the player
self.isDribbling = true;
self.dribbleStartTime = Date.now();
self.dribbleDuration = 1000; // 1 second
self.dribbleRadius = 120;
// Calculate angle from midfield to player
var angleToPlayer = Math.atan2(player.y - self.y, player.x - self.x);
self.dribbleStartAngle = angleToPlayer - Math.PI / 2;
self.dribbleEndAngle = angleToPlayer + Math.PI / 2;
self.dribbleOriginX = self.x;
self.dribbleOriginY = self.y;
self.hasDribbled = false;
}
if (self.isDribbling) {
var elapsed = Date.now() - self.dribbleStartTime;
var t = Math.min(elapsed / self.dribbleDuration, 1);
// Interpolate angle for half-circle
var angle = self.dribbleStartAngle + (self.dribbleEndAngle - self.dribbleStartAngle) * t;
self.x = self.dribbleOriginX + Math.cos(angle) * self.dribbleRadius;
self.y = self.dribbleOriginY + Math.sin(angle) * self.dribbleRadius;
// Ball follows midfield during dribble
if (distance < 80) {
ball.x = self.x;
ball.y = self.y;
ball.velocityX = 0;
ball.velocityY = 0;
}
// When dribble completes, shoot with curve
if (t >= 1 && !self.hasDribbled) {
self.hasDribbled = true;
self.isDribbling = false;
// Falsolu şut: apply curve by adding to X velocity
var goalDx = opponentGoal.x - ball.x;
var goalDy = opponentGoal.y - ball.y;
var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy);
if (goalDistance > 0) {
// Add curve: right-footed, so curve to the right (positive X)
var curveAmount = 7;
ball.velocityX = goalDx / goalDistance * 12 + curveAmount;
ball.velocityY = goalDy / goalDistance * 12;
ball.active = true;
}
}
}
}
}
} else {
// Return to midfield position
var homeDx = self.homeX - self.x;
var homeDy = self.homeY - self.y;
var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy);
if (homeDistance > 50) {
self.x += homeDx / homeDistance * self.speed * 0.3;
self.y += homeDy / homeDistance * self.speed * 0.3;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.hasBall = false;
return self;
});
var ReoPlayer = Container.expand(function (colorOverride) {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
if (typeof colorOverride === "number" && playerGraphics) {
playerGraphics.tint = colorOverride;
}
self.speed = 4;
self.role = 'reo';
self.homeX = 600;
self.homeY = 1800;
self.hasBall = false;
// Mode switching variables
self.isDefensiveMode = true;
self.defensiveColor = 0x000000; // Black
self.attackingColor = 0xffa500; // Orange
self.modeSwitch = 0;
self.modeSwitchInterval = 5000; // 5 seconds
// Chameleon ability variables
self.chameleonCooldown = 0;
self.chameleonInterval = 30000; // 30 seconds
self.copiedStats = null;
self.originalSpeed = 4;
self.originalDribbling = 1;
self.originalShot = 1;
// Copied ability variables
self.copiedWinterZone = false;
self.copiedWinterZoneRadius = 200;
self.copiedWinterZoneCooldown = 0;
self.copiedWinterZoneActive = false;
self.copiedWinterZoneDuration = 0;
self.copiedWinterZoneMaxDuration = 8000;
self.copiedSlowedOpponents = [];
self.copiedWinterZoneVisual = null;
self.copiedSpeedBurst = false;
self.copiedSpeedBurstCooldown = 0;
self.copiedSpeedBurstActive = false;
self.copiedBurstSpeed = 10;
self.copiedNormalSpeed = 4;
self.update = function () {
// Update mode switching
self.modeSwitch += 16;
if (self.modeSwitch >= self.modeSwitchInterval) {
self.modeSwitch = 0;
self.isDefensiveMode = !self.isDefensiveMode;
// Change color based on mode
if (self.isDefensiveMode) {
tween(playerGraphics, {
tint: self.defensiveColor
}, {
duration: 300
});
} else {
tween(playerGraphics, {
tint: self.attackingColor
}, {
duration: 300
});
}
}
// Update Chameleon cooldown
self.chameleonCooldown += 16;
if (self.chameleonCooldown >= self.chameleonInterval) {
self.chameleonCooldown = 0;
self.activateChameleon();
}
// Update copied abilities
if (self.copiedWinterZone) {
// Update Winter Zone cooldown
if (self.copiedWinterZoneCooldown > 0) {
self.copiedWinterZoneCooldown -= 16;
if (self.copiedWinterZoneCooldown < 0) self.copiedWinterZoneCooldown = 0;
}
// Winter Zone duration and effect
if (self.copiedWinterZoneActive) {
self.copiedWinterZoneDuration -= 16;
if (self.copiedWinterZoneDuration <= 0) {
self.copiedWinterZoneActive = false;
// Remove Winter Zone visual
if (self.copiedWinterZoneVisual) {
self.copiedWinterZoneVisual.destroy();
self.copiedWinterZoneVisual = null;
}
// Restore opponent speeds
for (var i = 0; i < self.copiedSlowedOpponents.length; i++) {
var opponent = self.copiedSlowedOpponents[i];
opponent.speed = opponent.originalSpeed || opponent.speed * 2;
}
self.copiedSlowedOpponents = [];
} else {
// Apply Winter Zone effect to nearby opponents
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y));
if (dist <= self.copiedWinterZoneRadius) {
if (self.copiedSlowedOpponents.indexOf(opponent) === -1) {
opponent.originalSpeed = opponent.speed;
opponent.speed = opponent.speed * 0.3; // Slow to 30% speed
self.copiedSlowedOpponents.push(opponent);
}
}
}
}
}
// Activate Winter Zone when opponents get close
if (!self.copiedWinterZoneActive && self.copiedWinterZoneCooldown <= 0) {
var nearbyOpponents = 0;
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
var dist = Math.sqrt((opponent.x - self.x) * (opponent.x - self.x) + (opponent.y - self.y) * (opponent.y - self.y));
if (dist <= self.copiedWinterZoneRadius + 50) {
nearbyOpponents++;
}
}
if (nearbyOpponents >= 2) {
// Activate Winter Zone
self.copiedWinterZoneActive = true;
self.copiedWinterZoneDuration = self.copiedWinterZoneMaxDuration;
self.copiedWinterZoneCooldown = 12000; // 12 seconds cooldown
// Create Winter Zone visual area
self.copiedWinterZoneVisual = self.addChild(LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4,
scaleY: 4,
tint: 0x87CEEB
}));
self.copiedWinterZoneVisual.alpha = 0.3;
// Visual effect
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x87CEEB
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1,
tint: self.isDefensiveMode ? self.defensiveColor : self.attackingColor
}, {
duration: 200
});
}
});
}
}
}
if (self.copiedSpeedBurst) {
// Update Speed Burst cooldown
if (self.copiedSpeedBurstCooldown > 0) {
self.copiedSpeedBurstCooldown -= 16;
if (self.copiedSpeedBurstCooldown < 0) self.copiedSpeedBurstCooldown = 0;
}
// Speed burst when close to ball
if (!self.copiedSpeedBurstActive && self.copiedSpeedBurstCooldown <= 0 && distance < 100) {
self.copiedSpeedBurstActive = true;
self.copiedSpeedBurstCooldown = 8000; // 8 seconds cooldown
self.speed = self.copiedBurstSpeed;
// Visual effect for speed burst
tween(self, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
}
});
// Speed burst lasts for 2 seconds
LK.setTimeout(function () {
self.copiedSpeedBurstActive = false;
self.speed = self.copiedNormalSpeed;
}, 2000);
}
}
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Mode-based behavior
if (self.isDefensiveMode) {
// Defensive mode: stay back and intercept
if (distance < 300) {
var defensiveSpeed = self.speed * 0.8;
self.x += dx / distance * defensiveSpeed;
self.y += dy / distance * defensiveSpeed;
// Defensive tackle
if (distance < 80) {
var clearX = ball.x < 1024 ? ball.x - 300 : ball.x + 300;
var clearY = ball.y - 200;
var clearDx = clearX - ball.x;
var clearDy = clearY - ball.y;
var clearDist = Math.sqrt(clearDx * clearDx + clearDy * clearDy);
if (clearDist > 0) {
ball.velocityX = clearDx / clearDist * 8;
ball.velocityY = clearDy / clearDist * 8;
}
}
} else {
// Return to defensive position
var homeDx = self.homeX - self.x;
var homeDy = self.homeY - self.y;
var homeDistance = Math.sqrt(homeDx * homeDx + homeDy * homeDy);
if (homeDistance > 50) {
self.x += homeDx / homeDistance * self.speed * 0.5;
self.y += homeDy / homeDistance * self.speed * 0.5;
}
}
} else {
// Attacking mode: chase ball aggressively
if (distance < 400) {
var attackSpeed = self.speed * 1.3;
self.x += dx / distance * attackSpeed;
self.y += dy / distance * attackSpeed;
// Attack shot
if (distance < 80) {
var goalDx = opponentGoal.x - ball.x;
var goalDy = opponentGoal.y - ball.y;
var goalDistance = Math.sqrt(goalDx * goalDx + goalDy * goalDy);
if (goalDistance > 0) {
ball.velocityX = goalDx / goalDistance * 12;
ball.velocityY = goalDy / goalDistance * 12;
}
}
}
}
};
self.activateChameleon = function () {
// Find random NPC to copy stats from (including player team members)
var availableNPCs = [];
for (var i = 0; i < opponents.length; i++) {
availableNPCs.push(opponents[i]);
}
// Also add player team members with special abilities
if (typeof hiori !== 'undefined') availableNPCs.push(hiori);
if (typeof chigiri !== 'undefined') availableNPCs.push(chigiri);
if (availableNPCs.length > 0) {
var randomNPC = availableNPCs[Math.floor(Math.random() * availableNPCs.length)];
// Copy stats from random NPC
self.copiedStats = {
speed: randomNPC.speed || self.originalSpeed,
dribbling: randomNPC.dribbleSpeed || self.originalDribbling,
shot: randomNPC.burstSpeed || self.originalShot,
role: randomNPC.role || 'reo'
};
// Apply copied stats
self.speed = self.copiedStats.speed;
// Copy special abilities based on role
if (self.copiedStats.role === 'hiori') {
// Copy Winter Zone ability
self.copiedWinterZone = true;
self.copiedWinterZoneRadius = 200;
self.copiedWinterZoneCooldown = 0;
self.copiedWinterZoneActive = false;
self.copiedWinterZoneDuration = 0;
self.copiedWinterZoneMaxDuration = 8000; // Slightly shorter than original
self.copiedSlowedOpponents = [];
self.copiedWinterZoneVisual = null;
} else if (self.copiedStats.role === 'chigiri') {
// Copy Speed Burst ability
self.copiedSpeedBurst = true;
self.copiedSpeedBurstCooldown = 0;
self.copiedSpeedBurstActive = false;
self.copiedBurstSpeed = 10;
self.copiedNormalSpeed = self.speed;
} else {
// Reset copied abilities
self.copiedWinterZone = false;
self.copiedSpeedBurst = false;
}
// Visual effect for Chameleon activation
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xff00ff
}, {
duration: 200,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1,
tint: self.isDefensiveMode ? self.defensiveColor : self.attackingColor
}, {
duration: 200
});
}
});
}
};
return self;
});
var SoccerBall = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.friction = 0.98;
self.active = true;
self.update = function () {
if (self.active) {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityX *= self.friction;
self.velocityY *= self.friction;
// Keep ball in bounds with bounce effect
if (self.x < 30) {
self.x = 30;
self.velocityX = Math.abs(self.velocityX) * 0.8;
}
if (self.x > 2018) {
self.x = 2018;
self.velocityX = -Math.abs(self.velocityX) * 0.8;
}
if (self.y < 30) {
self.y = 30;
self.velocityY = Math.abs(self.velocityY) * 0.8;
}
if (self.y > 2702) {
self.y = 2702;
self.velocityY = -Math.abs(self.velocityY) * 0.8;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
game.setBackgroundColor(0x228B22);
// Game variables
var opponents = [];
var playerScore = 0;
var opponentScore = 0;
var dragNode = null;
var maxStamina = 100;
var currentStamina = 100;
var staminaRegenRate = 0.2;
var staminaDrainRate = 0.5;
var lastPlayerX = 0;
var lastPlayerY = 0;
var shotChargeStart = 0;
var isChargingShot = false;
var shotPower = 0;
var maxShotPower = 20;
var minChargeTime = 2000; // 2 seconds minimum charge time
var lastTouchX = 0;
var lastTouchY = 0;
var ballDetachCooldown = 0;
var ballDetachCooldownTime = 1000; // 1 second cooldown
// UI Elements
var scoreTxt = new Text2('Player: 0 - Opponent: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Stamina UI
var staminaTxt = new Text2('Stamina: 100', {
size: 60,
fill: 0x00FF00
});
staminaTxt.anchor.set(0, 0);
staminaTxt.x = 50;
staminaTxt.y = 50;
LK.gui.topLeft.addChild(staminaTxt);
// Shot Power UI
var shotPowerTxt = new Text2('Shot Power: 0%', {
size: 60,
fill: 0xFFFFFF
});
shotPowerTxt.anchor.set(0, 0);
shotPowerTxt.x = 50;
shotPowerTxt.y = 130;
LK.gui.topLeft.addChild(shotPowerTxt);
// Game objects
var player = game.addChild(new Player());
player.x = 1024;
player.y = 2200;
var ball = game.addChild(new SoccerBall());
ball.x = 1024;
ball.y = 1366;
// Player's goal (bottom)
var playerGoal = game.addChild(new Goal());
playerGoal.x = 1024;
playerGoal.y = 2600;
// Opponent's goal (top)
var opponentGoal = game.addChild(new Goal());
opponentGoal.x = 1024;
opponentGoal.y = 300;
// Create opponents with specific roles
// Defense player (opponent)
var defensePlayer = game.addChild(new DefensePlayer());
defensePlayer.x = 1024;
defensePlayer.y = 600;
defensePlayer.homeX = 1024;
defensePlayer.homeY = 600;
opponents.push(defensePlayer);
// Chigiri - player team hybrid defender
var chigiri = game.addChild(new ChigiriPlayer(0x3399ff));
chigiri.x = 800;
chigiri.y = 2000;
chigiri.homeX = 800;
chigiri.homeY = 2000;
// Hiori - player team creative midfielder
var hiori = game.addChild(new HioriPlayer(0x6699ff));
hiori.x = 1200;
hiori.y = 2000;
hiori.homeX = 1200;
hiori.homeY = 2000;
// Reo - player team adaptive defender/attacker
var reo = game.addChild(new ReoPlayer(0x000000));
reo.x = 600;
reo.y = 1800;
reo.homeX = 600;
reo.homeY = 1800;
// Midfield player
var midfieldPlayer = game.addChild(new MidfieldPlayer());
midfieldPlayer.x = 1024;
midfieldPlayer.y = 1000;
midfieldPlayer.homeX = 1024;
midfieldPlayer.homeY = 1000;
opponents.push(midfieldPlayer);
// Forward player
var forwardPlayer = game.addChild(new ForwardPlayer());
forwardPlayer.x = 1024;
forwardPlayer.y = 1400;
forwardPlayer.homeX = 1024;
forwardPlayer.homeY = 1400;
opponents.push(forwardPlayer);
// Create goalkeepers
var playerGoalkeeper = game.addChild(new Goalkeeper(true)); // Blue goalkeeper for player team
playerGoalkeeper.x = 1024;
playerGoalkeeper.y = 2500; // In front of player's goal
playerGoalkeeper.originalX = 1024;
playerGoalkeeper.originalY = 2500;
var opponentGoalkeeper = game.addChild(new Goalkeeper(false)); // Red goalkeeper for opponent team
opponentGoalkeeper.x = 1024;
opponentGoalkeeper.y = 400; // In front of opponent's goal
opponentGoalkeeper.originalX = 1024;
opponentGoalkeeper.originalY = 400;
// Ball kicking mechanics
function kickBall(targetX, targetY, power) {
var dx = targetX - ball.x;
var dy = targetY - ball.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
var finalPower = power || Math.min(distance / 100, 15);
// Properly detach ball from player first
player.hasBall = false;
ball.active = true;
// Set cooldown to prevent immediate re-attachment
ballDetachCooldown = ballDetachCooldownTime;
// Apply velocity after detachment
ball.velocityX = dx / distance * finalPower;
ball.velocityY = dy / distance * finalPower;
LK.getSound('kick').play();
}
}
// Touch controls for player movement and ball kicking
game.down = function (x, y, obj) {
// Always update last touch position for shot direction
lastTouchX = x;
lastTouchY = y;
var playerDistance = Math.sqrt((x - player.x) * (x - player.x) + (y - player.y) * (y - player.y));
var ballDistance = Math.sqrt((x - ball.x) * (x - ball.x) + (y - ball.y) * (y - ball.y));
if (playerDistance < ballDistance) {
// Move player
dragNode = player;
} else {
// Start charging shot if player has ball
if (player.hasBall) {
shotChargeStart = Date.now();
isChargingShot = true;
shotPower = 0;
}
}
};
game.move = function (x, y, obj) {
// Always update last touch position for shot direction
lastTouchX = x;
lastTouchY = y;
if (dragNode && currentStamina > 0) {
var dx = x - dragNode.x;
var dy = y - dragNode.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Slow down movement and consume stamina - even slower when having ball
var moveSpeed = player.hasBall ? 0.15 : 0.2;
dragNode.x += dx * moveSpeed;
dragNode.y += dy * moveSpeed;
// Consume stamina based on movement
if (distance > 5) {
currentStamina -= staminaDrainRate;
if (currentStamina < 0) currentStamina = 0;
}
}
};
game.up = function (x, y, obj) {
dragNode = null;
// Handle shot release
if (isChargingShot && player.hasBall) {
var chargeTime = Date.now() - shotChargeStart;
if (chargeTime >= minChargeTime) {
// Release charged shot - use last touch position for direction
kickBall(lastTouchX, lastTouchY, shotPower);
} else {
// Not charged enough, no shot
}
isChargingShot = false;
shotPower = 0;
}
};
// Goal scoring function
function scoreGoal(isPlayer) {
if (isPlayer) {
playerScore++;
} else {
opponentScore++;
}
scoreTxt.setText('Player: ' + playerScore + ' - Opponent: ' + opponentScore);
LK.getSound('goal').play();
// Reset ball position
ball.x = 1024;
ball.y = 1366;
ball.velocityX = 0;
ball.velocityY = 0;
}
// Game update loop
game.update = function () {
// Update ball detach cooldown
if (ballDetachCooldown > 0) {
ballDetachCooldown -= 16; // Approximately 60 FPS
if (ballDetachCooldown < 0) ballDetachCooldown = 0;
}
// Check if player is close to ball for interaction (only if cooldown expired)
var playerToBallDistance = Math.sqrt((player.x - ball.x) * (player.x - ball.x) + (player.y - ball.y) * (player.y - ball.y));
if (playerToBallDistance < 80 && !player.hasBall && ballDetachCooldown <= 0) {
player.hasBall = true;
ball.active = false;
ball.velocityX = 0;
ball.velocityY = 0;
}
// If player has ball, make it stick to player
if (player.hasBall && ball.active === false) {
ball.x = player.x;
ball.y = player.y - 50;
}
// Stamina regeneration when not moving
var playerMoving = Math.abs(player.x - lastPlayerX) > 1 || Math.abs(player.y - lastPlayerY) > 1;
if (!playerMoving && currentStamina < maxStamina) {
currentStamina += staminaRegenRate;
if (currentStamina > maxStamina) currentStamina = maxStamina;
}
// Update last position
lastPlayerX = player.x;
lastPlayerY = player.y;
// Update stamina UI
var staminaPercent = Math.round(currentStamina / maxStamina * 100);
staminaTxt.setText('Stamina: ' + staminaPercent);
// Change color based on stamina level
if (staminaPercent > 50) {
staminaTxt.fill = 0x00FF00;
} else if (staminaPercent > 25) {
staminaTxt.fill = 0xFFFF00;
} else {
staminaTxt.fill = 0xFF0000;
}
// Update shot charging
if (isChargingShot && player.hasBall) {
var chargeTime = Date.now() - shotChargeStart;
if (chargeTime >= minChargeTime) {
// Calculate shot power based on charge time
var chargeProgress = Math.min((chargeTime - minChargeTime) / 1000, 1); // 1 second after minimum for max power
shotPower = 5 + chargeProgress * maxShotPower; // Minimum 5, maximum 25 power
var powerPercent = Math.round(chargeProgress * 100);
shotPowerTxt.setText('Shot Power: ' + powerPercent + '%');
shotPowerTxt.fill = 0x00FF00;
// Automatically kick ball forward when shot power reaches 100%
if (powerPercent >= 100) {
shotPower = 5 + maxShotPower; // Keep at maximum power
shotPowerTxt.setText('Shot Power: 100%');
shotPowerTxt.fill = 0x00FF00;
// Auto-kick ball forward when power reaches 100%
var forwardX = player.x;
var forwardY = player.y - 300; // Kick forward (up the field)
kickBall(forwardX, forwardY, shotPower);
isChargingShot = false;
shotPower = 0;
}
} else {
// Not charged enough yet
var timeLeft = Math.ceil((minChargeTime - chargeTime) / 1000);
shotPowerTxt.setText('Hold for ' + timeLeft + 's');
shotPowerTxt.fill = 0xFFFF00;
}
} else {
shotPowerTxt.setText('Shot Power: 0%');
shotPowerTxt.fill = 0xFFFFFF;
}
// Check player goal scoring (opponent scores)
if (ball.y > playerGoal.y - 50 && ball.x > playerGoal.x - 200 && ball.x < playerGoal.x + 200) {
scoreGoal(false);
LK.effects.flashObject(playerGoal, 0xFF0000, 500);
}
// Check opponent goal scoring (player scores)
if (ball.y < opponentGoal.y + 50 && ball.x > opponentGoal.x - 200 && ball.x < opponentGoal.x + 200) {
scoreGoal(true);
LK.effects.flashObject(opponentGoal, 0x00FF00, 500);
}
// Check win condition
if (playerScore >= 5) {
LK.showYouWin();
}
if (opponentScore >= 5) {
LK.showGameOver();
}
// Enhanced AI positioning based on ball location
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
var ballThreatLevel = Math.sqrt((ball.x - 1024) * (ball.x - 1024) + (ball.y - 1366) * (ball.y - 1366));
// Adjust opponent aggression based on ball threat
if (ballThreatLevel < 300) {
// Ball is in center - all opponents become more aggressive
if (opponent.role === 'defense') {
opponent.speed = 4.5;
opponent.maxDistance = 500;
} else if (opponent.role === 'midfield') {
opponent.speed = 3.5;
} else if (opponent.role === 'forward') {
opponent.speed = 4.2;
}
} else {
// Ball is far - return to normal behavior
if (opponent.role === 'defense') {
opponent.speed = 4;
opponent.maxDistance = 400;
} else if (opponent.role === 'midfield') {
opponent.speed = 3;
} else if (opponent.role === 'forward') {
opponent.speed = 3.5;
}
}
}
// Role-based AI is now handled in each player's update method
// Defense, Midfield, and Forward players have their own specialized behaviors
};