/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Ball class var Ball = Container.expand(function () { var self = Container.call(this); // Attach ball asset (ellipse, white) var ballAsset = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Ball properties self.radius = ballAsset.width / 2; self.vx = 0; self.vy = 0; self.friction = 0.98; // Ball slows down over time // Update method (called every tick) self.update = function () { self.x += self.vx; self.y += self.vy; self.vx *= self.friction; self.vy *= self.friction; // Clamp speed to zero if very small if (Math.abs(self.vx) < 0.1) self.vx = 0; if (Math.abs(self.vy) < 0.1) self.vy = 0; }; return self; }); // Goal class var Goal = Container.expand(function (assetId) { var self = Container.call(this); // Attach goal asset (rectangle) var goalAsset = self.attachAsset(assetId || 'goal', { anchorX: 0.5, anchorY: 0.5 }); self.width = goalAsset.width; self.height = goalAsset.height; return self; }); // Goalkeeper class var Goalkeeper = Container.expand(function () { var self = Container.call(this); // Attach different asset for each goalkeeper, set in setTeam var keeperAsset = null; self.radius = 60; self.team = 0; // 0: top, 1: bottom // Set asset and color for each team self.setTeam = function (team) { self.team = team; if (keeperAsset) { self.removeChild(keeperAsset); } if (team === 0) { // Top goalkeeper: use a unique asset (e.g. 'goalkeeperA') keeperAsset = self.attachAsset('goalkeeperA', { anchorX: 0.5, anchorY: 0.5 }); keeperAsset.width = 120; keeperAsset.height = 120; } else { // Bottom goalkeeper: use a unique asset (e.g. 'goalkeeperB') keeperAsset = self.attachAsset('goalkeeperB', { anchorX: 0.5, anchorY: 0.5 }); keeperAsset.width = 120; keeperAsset.height = 120; } }; // Update method: move along goal line to follow ball X, clamp inside goal self.update = function () { var goal, minX, maxX, yPos; if (self.team === 0) { goal = topGoal; yPos = goal.y + 10; } else { goal = bottomGoal; yPos = goal.y - 10; } // Move X toward ball.x, but clamp inside goal width var isLevel2 = !!self.level2; var targetX = Math.max(goal.x - goal.width / 2 + self.radius, Math.min(ball.x, goal.x + goal.width / 2 - self.radius)); // Smooth follow (further reduced reflex: was 0.13, now 0.07) self.x += (targetX - self.x) * (isLevel2 ? 0.18 : 0.07); // Level 2: çok daha hızlı refleks self.y = yPos; // Goalkeeper tries to block ball if close var dx = ball.x - self.x; var dy = ball.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.radius + ball.radius + (isLevel2 ? 40 : 20)) { // Block: push ball away from goal (further reduced block power: was 4.5, now 2.5) var blockAngle = Math.atan2(dy, dx); var blockPower = isLevel2 ? 7 : 2.5; // Level 2: çok daha güçlü blok ball.vx += Math.cos(blockAngle) * blockPower; ball.vy += Math.sin(blockAngle) * blockPower; // Clamp ball velocity to prevent excessive speed var maxBallSpeed = isLevel2 ? 28 : 18; var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy); if (speed > maxBallSpeed) { ball.vx = ball.vx / speed * maxBallSpeed; ball.vy = ball.vy / speed * maxBallSpeed; } // Move ball slightly away from keeper to avoid sticking ball.x = self.x + Math.cos(blockAngle) * (self.radius + ball.radius + 2); ball.y = self.y + Math.sin(blockAngle) * (self.radius + ball.radius + 2); } }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); // Attach player asset (circle, color depends on team) var playerAsset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.radius = playerAsset.width / 2; self.team = 0; // 0: left, 1: right self.index = 0; // 0-5 self.isUser = false; // Only one player is user-controlled // For AI: target position self.targetX = self.x; self.targetY = self.y; // For user drag self.isDragging = false; // Update method self.update = function () { // Store lastX, lastY for teleport logic if (typeof self.lastX === "undefined") self.lastX = self.x; if (typeof self.lastY === "undefined") self.lastY = self.y; // --- Teleport to center if player reaches a top corner --- // Define top left and top right corner areas var cornerMargin = 80; var topCornerY = field.top + self.radius + 10; var leftCornerX = field.left + self.radius + 10; var rightCornerX = field.right - self.radius - 10; var centerX = 2048 / 2; var centerY = 2732 / 2; // Check if player just entered top left corner if (self.lastX > leftCornerX + cornerMargin && self.x <= leftCornerX + cornerMargin && self.lastY > topCornerY + cornerMargin && self.y <= topCornerY + cornerMargin) { LK.showGameOver(); // Restart match automatically return; } // Check if player just entered top right corner if (self.lastX < rightCornerX - cornerMargin && self.x >= rightCornerX - cornerMargin && self.lastY > topCornerY + cornerMargin && self.y <= topCornerY + cornerMargin) { LK.showGameOver(); // Restart match automatically return; } if (!self.isUser) { // AI logic for teamB only if (self.team === 1) { // Level 2'de AI daha hızlı ve daha iyi oynasın var isLevel2 = !!self.level2; // TeamB AI: ONLY attack user's goal (topGoal), never own goal // If close to ball, move toward ball and try to shoot toward topGoal var dx = ball.x - self.x; var dy = ball.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); // Only try to kick toward topGoal (never own goal) if (dist < (isLevel2 ? 180 : 120)) { // Try to "kick" the ball toward topGoal if close enough var goalDx = topGoal.x - ball.x; var goalDy = topGoal.y - ball.y; var goalDist = Math.sqrt(goalDx * goalDx + goalDy * goalDy); if (goalDist > 0) { // Simulate a kick if close enough to ball if (dist < self.radius + ball.radius + 10) { ball.vx += goalDx / goalDist * (isLevel2 ? 12 : 7); // Level 2: çok daha güçlü şut ball.vy += goalDy / goalDist * (isLevel2 ? 12 : 7); lastTeamTouched = 1; } } // Move toward ball self.x += dx / dist * (isLevel2 ? 16 : 9); // Level 2: çok daha hızlı hareket self.y += dy / dist * (isLevel2 ? 16 : 9); } else { // Move toward a position between ball and topGoal (attack position) var attackX = ball.x; var attackY = ball.y + (isLevel2 ? 180 : 100); var adx = attackX - self.x; var ady = attackY - self.y; var adist = Math.sqrt(adx * adx + ady * ady); if (adist > 10) { self.x += adx / adist * (isLevel2 ? 10 : 6); // Level 2: daha hızlı pozisyon alma self.y += ady / adist * (isLevel2 ? 10 : 6); } } } } // Clamp inside field (vertical orientation) if (self.x < field.left + self.radius) self.x = field.left + self.radius; if (self.x > field.right - self.radius) self.x = field.right - self.radius; if (self.y < field.top + self.radius) self.y = field.top + self.radius; if (self.y > field.bottom - self.radius) self.y = field.bottom - self.radius; // Update lastX, lastY for next frame self.lastX = self.x; self.lastY = self.y; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a8f3c, // Football field green fullscreen: true }); /**** * Game Code ****/ // Tween plugin for animations (not used in MVP but included for future use) // Field dimensions (full screen, no margins) var field = { width: 2048, height: 2732, left: 0, right: 2048, top: 0, bottom: 2732 }; // Play background music continuously LK.playMusic('2'); // Draw field (rectangle, lines, center circle, etc.) var fieldAsset = LK.getAsset('field', { width: field.width, height: field.height, color: 0x2e7d32, // More realistic football field green shape: 'box', x: field.left, y: field.top }); game.addChild(fieldAsset); // Center line (horizontal now) var centerLine = LK.getAsset('centerLine', { width: 10, height: field.height, color: 0xffffff, shape: 'box', x: field.left + field.width / 2 - 5, y: field.top }); game.addChild(centerLine); // Penalty areas (top and bottom) var penaltyWidth = 900; var penaltyHeight = 300; var topPenalty = LK.getAsset('penaltyAreaLeft', { width: penaltyWidth, height: penaltyHeight, color: 0xffffff, shape: 'box', x: field.left + field.width / 2 - penaltyWidth / 2, y: field.top - 5 }); topPenalty.alpha = 0.12; game.addChild(topPenalty); var bottomPenalty = LK.getAsset('penaltyAreaRight', { width: penaltyWidth, height: penaltyHeight, color: 0xffffff, shape: 'box', x: field.left + field.width / 2 - penaltyWidth / 2, y: field.bottom - penaltyHeight + 5 }); bottomPenalty.alpha = 0.12; game.addChild(bottomPenalty); // Goal areas (top and bottom) var goalAreaWidth = 500; var goalAreaHeight = 180; var topGoalArea = LK.getAsset('goalAreaLeft', { width: goalAreaWidth, height: goalAreaHeight, color: 0xffffff, shape: 'box', x: field.left + field.width / 2 - goalAreaWidth / 2, y: field.top - 5 }); topGoalArea.alpha = 0.18; game.addChild(topGoalArea); var bottomGoalArea = LK.getAsset('goalAreaRight', { width: goalAreaWidth, height: goalAreaHeight, color: 0xffffff, shape: 'box', x: field.left + field.width / 2 - goalAreaWidth / 2, y: field.bottom - goalAreaHeight + 5 }); bottomGoalArea.alpha = 0.18; game.addChild(bottomGoalArea); // Penalty spots var penaltySpotRadius = 18; var topPenaltySpot = LK.getAsset('penaltySpotLeft', { width: penaltySpotRadius * 2, height: penaltySpotRadius * 2, color: 0xffffff, shape: 'ellipse', x: field.left + field.width / 2 - penaltySpotRadius, y: field.top + 120 }); topPenaltySpot.alpha = 0.7; game.addChild(topPenaltySpot); var bottomPenaltySpot = LK.getAsset('penaltySpotRight', { width: penaltySpotRadius * 2, height: penaltySpotRadius * 2, color: 0xffffff, shape: 'ellipse', x: field.left + field.width / 2 - penaltySpotRadius, y: field.bottom - 120 - penaltySpotRadius * 2 }); bottomPenaltySpot.alpha = 0.7; game.addChild(bottomPenaltySpot); // Center circle var centerCircle = LK.getAsset('centerCircle', { width: 320, height: 320, color: 0xffffff, shape: 'ellipse', x: field.left + field.width / 2 - 160, y: field.top + field.height / 2 - 160 }); centerCircle.alpha = 0.25; game.addChild(centerCircle); // Center spot var centerSpot = LK.getAsset('centerSpot', { width: 24, height: 24, color: 0xffffff, shape: 'ellipse', x: field.left + field.width / 2 - 12, y: field.top + field.height / 2 - 12 }); centerSpot.alpha = 0.7; game.addChild(centerSpot); // Corner arcs (for visual, not used in logic) for (var i = 0; i < 4; i++) { var cx = i < 2 ? field.left : field.right; var cy = i % 2 === 0 ? field.top : field.bottom; var cornerArc = LK.getAsset('cornerArc' + i, { width: 60, height: 60, color: 0xffffff, shape: 'ellipse', x: cx - 30, y: cy - 30 }); cornerArc.alpha = 0.15; game.addChild(cornerArc); } // Goals (top and bottom) var goalWidth = 400; var goalHeight = 120; var topGoal = new Goal('goalTop'); var bottomGoal = new Goal('goalBottom'); topGoal.x = field.left + field.width / 2; topGoal.y = field.top - 20 + goalHeight / 2; bottomGoal.x = field.left + field.width / 2; bottomGoal.y = field.bottom + 20 - goalHeight / 2; topGoal.width = goalWidth; topGoal.height = goalHeight; bottomGoal.width = goalWidth; bottomGoal.height = goalHeight; game.addChild(topGoal); game.addChild(bottomGoal); // Ball var ball = new Ball(); ball.x = field.left + field.width / 2; ball.y = field.top + field.height / 2; var ballAsset = ball.children[0]; // Make the ball slightly smaller ballAsset.width = 100; ballAsset.height = 100; ball.radius = 50; ballAsset.color = 0xffffff; game.addChild(ball); // Teams var teamA = []; var teamB = []; var playerRadius = 90; var playerColors = [0x1e90ff, 0xff3333]; // Blue, Red // Add goalkeeper for teamA (top) var keeperA = new Goalkeeper(); keeperA.setTeam(0); keeperA.x = topGoal.x; keeperA.y = topGoal.y + 10; game.addChild(keeperA); // Place teamA (top, blue) - only 1 player for (var i = 0; i < 1; i++) { var p = new Player(); var asset = p.children[0]; asset.width = playerRadius * 2 * 1.2; asset.height = playerRadius * 2 * 1.2; asset.color = playerColors[0]; p.radius = playerRadius * 1.2; p.team = 0; p.index = i; // Place at slightly left of center (Messi) p.x = field.left + field.width / 2 - 220; p.y = field.top + 400; // User-controlled p.isUser = true; teamA.push(p); game.addChild(p); } // Add goalkeeper for teamB (bottom) var keeperB = new Goalkeeper(); keeperB.setTeam(1); keeperB.x = bottomGoal.x; keeperB.y = bottomGoal.y - 10; game.addChild(keeperB); // Place teamB (bottom, red) - only 1 player for (var i = 0; i < 1; i++) { var p = new Player(); // Replace default asset with teamB asset p.removeChild(p.children[0]); var asset = p.attachAsset('playerB', { anchorX: 0.5, anchorY: 0.5 }); asset.width = playerRadius * 2 * 1.2; asset.height = playerRadius * 2 * 1.2; asset.color = playerColors[1]; p.radius = playerRadius * 1.2; p.team = 1; p.index = i; // Place at slightly right of center (Ronaldo) p.x = field.left + field.width / 2 + 220; p.y = field.bottom - 400; p.isUser = false; // AI teamB.push(p); game.addChild(p); } // Score var scoreA = 0; var scoreB = 0; var scoreTxt = new Text2('0 - 0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // GOAL! text (hidden by default) var goalText = new Text2('GOAL!', { size: 220, fill: 0xFFD700, font: "Impact, Arial Black, Tahoma" }); goalText.anchor.set(0.5, 0.5); goalText.visible = false; LK.gui.center.addChild(goalText); // Helper: show GOAL! text for a short time function showGoalText() { goalText.visible = true; goalText.alpha = 1; // Hide after 1 second LK.setTimeout(function () { goalText.visible = false; goalText.alpha = 1; }, 1000); } // Game state var lastTouch = { x: 0, y: 0 }; var draggingPlayer = null; var throwInActive = false; var throwInTeam = 0; var throwInPos = { x: 0, y: 0 }; var cornerActive = false; var cornerTeam = 0; var cornerPos = { x: 0, y: 0 }; var lastTeamTouched = 0; // 0: teamA, 1: teamB // Helper: check collision between two circles function circlesCollide(ax, ay, ar, bx, by, br) { var dx = ax - bx; var dy = ay - by; var dist = Math.sqrt(dx * dx + dy * dy); return dist < ar + br; } // Helper: check if ball is in goal function isGoal(ball, goal) { return ball.y > goal.y - goal.height / 2 && ball.y < goal.y + goal.height / 2 && ball.x > goal.x - goal.width / 2 && ball.x < goal.x + goal.width / 2; } // Helper: reset positions after goal function resetPositions() { // Ball to center ball.x = field.left + field.width / 2; ball.y = field.top + field.height / 2; ball.vx = 0; ball.vy = 0; // TeamA (top) for (var i = 0; i < 1; i++) { var p = teamA[i]; p.x = field.left + field.width / 2 - 220; p.y = field.top + 400; p.radius = playerRadius * 1.2; } // TeamB (bottom) for (var i = 0; i < 1; i++) { var p = teamB[i]; p.x = field.left + field.width / 2 + 220; p.y = field.bottom - 400; p.radius = playerRadius * 1.2; } // Reset goalkeepers keeperA.x = topGoal.x; keeperA.y = topGoal.y + 10; keeperB.x = bottomGoal.x; keeperB.y = bottomGoal.y - 10; } // Helper: check if ball is out for throw-in or corner function checkOutOfBounds() { // Top/bottom (taç) if (ball.y < field.top) { throwInActive = true; throwInTeam = 1; // Bottom team gets throw-in throwInPos.y = field.top + ball.radius + 10; throwInPos.x = Math.max(field.left + ball.radius + 10, Math.min(ball.x, field.right - ball.radius - 10)); ball.vx = 0; ball.vy = 0; ball.y = throwInPos.y; ball.x = throwInPos.x; } else if (ball.y > field.bottom) { throwInActive = true; throwInTeam = 0; // Top team gets throw-in throwInPos.y = field.bottom - ball.radius - 10; throwInPos.x = Math.max(field.left + ball.radius + 10, Math.min(ball.x, field.right - ball.radius - 10)); ball.vx = 0; ball.vy = 0; ball.y = throwInPos.y; ball.x = throwInPos.x; } // Left/right (korner veya aut) else if (ball.x < field.left) { // If ball is between goal posts, it's a goal if (ball.y > topGoal.y - topGoal.height / 2 && ball.y < topGoal.y + topGoal.height / 2) { // Top goal scoreB++; scoreTxt.setText(scoreA + " - " + scoreB); showGoalText(); resetPositions(); return; } // Otherwise, corner or goal kick if (ball.y < field.top + 200) { // Top left corner cornerActive = true; cornerTeam = 1; // Bottom team gets corner cornerPos.x = field.left + 30; cornerPos.y = field.top + 30; } else if (ball.y > field.bottom - 200) { // Bottom left corner cornerActive = true; cornerTeam = 0; // Top team gets corner cornerPos.x = field.left + 30; cornerPos.y = field.bottom - 30; } else { // Goal kick (not implemented, treat as throw-in for now) throwInActive = true; throwInTeam = lastTeamTouched === 0 ? 1 : 0; throwInPos.y = Math.max(field.top + ball.radius + 10, Math.min(ball.y, field.bottom - ball.radius - 10)); throwInPos.x = field.left + ball.radius + 10; } ball.vx = 0; ball.vy = 0; if (cornerActive) { ball.x = cornerPos.x; ball.y = cornerPos.y; } else { ball.x = throwInPos.x; ball.y = throwInPos.y; } } else if (ball.x > field.right) { // If ball is between goal posts, it's a goal if (ball.y > bottomGoal.y - bottomGoal.height / 2 && ball.y < bottomGoal.y + bottomGoal.height / 2) { // Bottom goal scoreA++; scoreTxt.setText(scoreA + " - " + scoreB); showGoalText(); resetPositions(); return; } // Otherwise, corner or goal kick if (ball.y < field.top + 200) { // Top right corner cornerActive = true; cornerTeam = 1; // Bottom team gets corner cornerPos.x = field.right - 30; cornerPos.y = field.top + 30; } else if (ball.y > field.bottom - 200) { // Bottom right corner cornerActive = true; cornerTeam = 0; // Top team gets corner cornerPos.x = field.right - 30; cornerPos.y = field.bottom - 30; } else { // Goal kick (not implemented, treat as throw-in for now) throwInActive = true; throwInTeam = lastTeamTouched === 0 ? 1 : 0; throwInPos.y = Math.max(field.top + ball.radius + 10, Math.min(ball.y, field.bottom - ball.radius - 10)); throwInPos.x = field.right - ball.radius - 10; } ball.vx = 0; ball.vy = 0; if (cornerActive) { ball.x = cornerPos.x; ball.y = cornerPos.y; } else { ball.x = throwInPos.x; ball.y = throwInPos.y; } } } // Touch/drag logic for user player game.down = function (x, y, obj) { // Only allow drag if not in throw-in/corner if (throwInActive || cornerActive) return; // Check if any user player is touched (all teamA) for (var i = 0; i < teamA.length; i++) { var userPlayer = teamA[i]; var dx = x - userPlayer.x; var dy = y - userPlayer.y; if (dx * dx + dy * dy < userPlayer.radius * userPlayer.radius) { draggingPlayer = userPlayer; draggingPlayer.isDragging = true; lastTouch.x = x; lastTouch.y = y; break; } } }; game.move = function (x, y, obj) { if (draggingPlayer && draggingPlayer.isDragging) { // Move player with finger, clamp inside field (vertical) draggingPlayer.x = Math.max(field.left + draggingPlayer.radius, Math.min(x, field.right - draggingPlayer.radius)); draggingPlayer.y = Math.max(field.top + draggingPlayer.radius, Math.min(y, field.bottom - draggingPlayer.radius)); lastTouch.x = x; lastTouch.y = y; } }; game.up = function (x, y, obj) { if (draggingPlayer && draggingPlayer.isDragging) { // On release, if close to ball, kick it var dx = ball.x - draggingPlayer.x; var dy = ball.y - draggingPlayer.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < draggingPlayer.radius + ball.radius + 10) { // Kick direction: from player to ball, magnitude based on drag var kickVx = (ball.x - lastTouch.x) * 0.3; var kickVy = (ball.y - lastTouch.y) * 0.3; ball.vx += kickVx; ball.vy += kickVy; lastTeamTouched = 0; } draggingPlayer.isDragging = false; draggingPlayer = null; } // Throw-in/corner logic if (throwInActive) { // Only allow throw-in by correct team if (throwInTeam === 0) { // Left team var dx = x - ball.x; var dy = y - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 30) { ball.vx = dx * 0.15; ball.vy = dy * 0.15; throwInActive = false; } } if (throwInTeam === 1) { // Right team var dx = x - ball.x; var dy = y - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 30) { ball.vx = dx * 0.15; ball.vy = dy * 0.15; throwInActive = false; } } } if (cornerActive) { // Only allow corner by correct team if (cornerTeam === 0) { // Left team var dx = x - ball.x; var dy = y - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 30) { ball.vx = dx * 0.15; ball.vy = dy * 0.15; cornerActive = false; } } if (cornerTeam === 1) { // Right team var dx = x - ball.x; var dy = y - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 30) { ball.vx = dx * 0.15; ball.vy = dy * 0.15; cornerActive = false; } } } }; // Main game update game.update = function () { // Update goalkeepers keeperA.update(); keeperB.update(); // Update all players for (var i = 0; i < 1; i++) { teamA[i].update(); teamB[i].update(); } // Update ball ball.update(); // Ball-player collision for (var i = 0; i < 1; i++) { var p = teamA[i]; var dx = ball.x - p.x; var dy = ball.y - p.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < ball.radius + p.radius) { // Push ball away var overlap = ball.radius + p.radius - dist + 1; var nx = dx / dist; var ny = dy / dist; ball.x += nx * overlap; ball.y += ny * overlap; // Ball velocity: if user player, shoot fast! if (p.isUser) { // Shoot with high speed in the direction from player to ball var shootPower = 18; ball.vx = nx * shootPower; ball.vy = ny * shootPower; } else { ball.vx += nx * 2; ball.vy += ny * 2; } lastTeamTouched = 0; } var p2 = teamB[i]; dx = ball.x - p2.x; dy = ball.y - p2.y; dist = Math.sqrt(dx * dx + dy * dy); if (dist < ball.radius + p2.radius) { var overlap = ball.radius + p2.radius - dist + 1; var nx = dx / dist; var ny = dy / dist; ball.x += nx * overlap; ball.y += ny * overlap; ball.vx += nx * 2; ball.vy += ny * 2; lastTeamTouched = 1; } } // Ball-wall collision (field boundaries) // --- Korner invisible wall logic --- // Define korner (corner) area size var kornerMargin = 120; // px from each edge (adjust as needed) var centerX = field.left + field.width / 2; var centerY = field.top + field.height / 2; // Top left korner if (ball.x < field.left + kornerMargin && ball.y < field.top + kornerMargin) { // Slide ball toward center var dx = centerX - ball.x; var dy = centerY - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var slideSpeed = 12; ball.vx = dx / dist * slideSpeed; ball.vy = dy / dist * slideSpeed; // Move ball slightly out of the corner to avoid repeated triggers ball.x = field.left + kornerMargin + ball.radius; ball.y = field.top + kornerMargin + ball.radius; } } // Top right korner if (ball.x > field.right - kornerMargin && ball.y < field.top + kornerMargin) { var dx = centerX - ball.x; var dy = centerY - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var slideSpeed = 12; ball.vx = dx / dist * slideSpeed; ball.vy = dy / dist * slideSpeed; ball.x = field.right - kornerMargin - ball.radius; ball.y = field.top + kornerMargin + ball.radius; } } // Bottom left korner if (ball.x < field.left + kornerMargin && ball.y > field.bottom - kornerMargin) { var dx = centerX - ball.x; var dy = centerY - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var slideSpeed = 12; ball.vx = dx / dist * slideSpeed; ball.vy = dy / dist * slideSpeed; ball.x = field.left + kornerMargin + ball.radius; ball.y = field.bottom - kornerMargin - ball.radius; } } // Bottom right korner if (ball.x > field.right - kornerMargin && ball.y > field.bottom - kornerMargin) { var dx = centerX - ball.x; var dy = centerY - ball.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { var slideSpeed = 12; ball.vx = dx / dist * slideSpeed; ball.vy = dy / dist * slideSpeed; ball.x = field.right - kornerMargin - ball.radius; ball.y = field.bottom - kornerMargin - ball.radius; } } // Standard wall collision (field boundaries) if (ball.x < field.left + ball.radius) { ball.x = field.left + ball.radius; ball.vx = -ball.vx * 0.7; } if (ball.x > field.right - ball.radius) { ball.x = field.right - ball.radius; ball.vx = -ball.vx * 0.7; } if (ball.y < field.top + ball.radius) { ball.y = field.top + ball.radius; ball.vy = -ball.vy * 0.7; } if (ball.y > field.bottom - ball.radius) { ball.y = field.bottom - ball.radius; ball.vy = -ball.vy * 0.7; } // Check for goals if (isGoal(ball, topGoal)) { scoreB++; scoreTxt.setText(scoreA + " - " + scoreB); showGoalText(); resetPositions(); return; } if (isGoal(ball, bottomGoal)) { scoreA++; scoreTxt.setText(scoreA + " - " + scoreB); showGoalText(); resetPositions(); return; } // Check for throw-in/corner if (!throwInActive && !cornerActive) { checkOutOfBounds(); } // Win condition (first to 5 or 10, level system) if (typeof gameLevel === "undefined") gameLevel = 1; if (typeof level2Inited === "undefined") level2Inited = false; // Level 1: 5 gole ilk ulaşan kazanır, Level 2: 10 gole ilk ulaşan kazanır if (gameLevel === 1) { if (scoreA >= 5) { // Level 1 kazanıldı, Level 2 başlat gameLevel = 2; level2Inited = false; // Skorları sıfırla, pozisyonları sıfırla, GOAL! yazısı gösterme scoreA = 0; scoreB = 0; scoreTxt.setText(scoreA + " - " + scoreB); resetPositions(); // Level 2 başlatıldığında AI hızını artırmak için flag level2Inited = false; // Kısa bir "Level 2" yazısı göster if (typeof levelText === "undefined") { levelText = new Text2('NOW Angry Messi !!!', { size: 180, fill: 0xFF0000, // Kırmızı renk font: "Impact, Arial Black, Tahoma" }); levelText.anchor.set(0.5, 0.5); // Place Angry Messi just below GOAL! text // GOAL! text is centered at gui.center, so we offset Y by its height + margin // Use goalText.height if available, otherwise use a fixed offset var goalTextOffset = (goalText && goalText.height ? goalText.height : 220) / 2; levelText.y = goalText.y + goalTextOffset + 80; // 80px margin below GOAL! LK.gui.center.addChild(levelText); } levelText.visible = true; levelText.alpha = 1; LK.setTimeout(function () { levelText.visible = false; }, 3000); // 3 saniye göster return; } if (scoreB >= 5) { LK.showGameOver(); return; } } else if (gameLevel === 2) { // Level 2'de AI daha hızlı ve daha iyi oynasın if (!level2Inited) { // AI hız ve zorluk parametrelerini artır // teamB AI için parametreleri güncelle for (var i = 0; i < teamB.length; i++) { var p = teamB[i]; p.level2 = true; // AI update fonksiyonunda kontrol edilecek } // Kaleci refleksini de artır keeperB.level2 = true; level2Inited = true; } if (scoreA >= 10) { LK.showYouWin(); return; } if (scoreB >= 10) { LK.showGameOver(); return; } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ball class
var Ball = Container.expand(function () {
var self = Container.call(this);
// Attach ball asset (ellipse, white)
var ballAsset = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Ball properties
self.radius = ballAsset.width / 2;
self.vx = 0;
self.vy = 0;
self.friction = 0.98; // Ball slows down over time
// Update method (called every tick)
self.update = function () {
self.x += self.vx;
self.y += self.vy;
self.vx *= self.friction;
self.vy *= self.friction;
// Clamp speed to zero if very small
if (Math.abs(self.vx) < 0.1) self.vx = 0;
if (Math.abs(self.vy) < 0.1) self.vy = 0;
};
return self;
});
// Goal class
var Goal = Container.expand(function (assetId) {
var self = Container.call(this);
// Attach goal asset (rectangle)
var goalAsset = self.attachAsset(assetId || 'goal', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = goalAsset.width;
self.height = goalAsset.height;
return self;
});
// Goalkeeper class
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
// Attach different asset for each goalkeeper, set in setTeam
var keeperAsset = null;
self.radius = 60;
self.team = 0; // 0: top, 1: bottom
// Set asset and color for each team
self.setTeam = function (team) {
self.team = team;
if (keeperAsset) {
self.removeChild(keeperAsset);
}
if (team === 0) {
// Top goalkeeper: use a unique asset (e.g. 'goalkeeperA')
keeperAsset = self.attachAsset('goalkeeperA', {
anchorX: 0.5,
anchorY: 0.5
});
keeperAsset.width = 120;
keeperAsset.height = 120;
} else {
// Bottom goalkeeper: use a unique asset (e.g. 'goalkeeperB')
keeperAsset = self.attachAsset('goalkeeperB', {
anchorX: 0.5,
anchorY: 0.5
});
keeperAsset.width = 120;
keeperAsset.height = 120;
}
};
// Update method: move along goal line to follow ball X, clamp inside goal
self.update = function () {
var goal, minX, maxX, yPos;
if (self.team === 0) {
goal = topGoal;
yPos = goal.y + 10;
} else {
goal = bottomGoal;
yPos = goal.y - 10;
}
// Move X toward ball.x, but clamp inside goal width
var isLevel2 = !!self.level2;
var targetX = Math.max(goal.x - goal.width / 2 + self.radius, Math.min(ball.x, goal.x + goal.width / 2 - self.radius));
// Smooth follow (further reduced reflex: was 0.13, now 0.07)
self.x += (targetX - self.x) * (isLevel2 ? 0.18 : 0.07); // Level 2: çok daha hızlı refleks
self.y = yPos;
// Goalkeeper tries to block ball if close
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < self.radius + ball.radius + (isLevel2 ? 40 : 20)) {
// Block: push ball away from goal (further reduced block power: was 4.5, now 2.5)
var blockAngle = Math.atan2(dy, dx);
var blockPower = isLevel2 ? 7 : 2.5; // Level 2: çok daha güçlü blok
ball.vx += Math.cos(blockAngle) * blockPower;
ball.vy += Math.sin(blockAngle) * blockPower;
// Clamp ball velocity to prevent excessive speed
var maxBallSpeed = isLevel2 ? 28 : 18;
var speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
if (speed > maxBallSpeed) {
ball.vx = ball.vx / speed * maxBallSpeed;
ball.vy = ball.vy / speed * maxBallSpeed;
}
// Move ball slightly away from keeper to avoid sticking
ball.x = self.x + Math.cos(blockAngle) * (self.radius + ball.radius + 2);
ball.y = self.y + Math.sin(blockAngle) * (self.radius + ball.radius + 2);
}
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset (circle, color depends on team)
var playerAsset = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = playerAsset.width / 2;
self.team = 0; // 0: left, 1: right
self.index = 0; // 0-5
self.isUser = false; // Only one player is user-controlled
// For AI: target position
self.targetX = self.x;
self.targetY = self.y;
// For user drag
self.isDragging = false;
// Update method
self.update = function () {
// Store lastX, lastY for teleport logic
if (typeof self.lastX === "undefined") self.lastX = self.x;
if (typeof self.lastY === "undefined") self.lastY = self.y;
// --- Teleport to center if player reaches a top corner ---
// Define top left and top right corner areas
var cornerMargin = 80;
var topCornerY = field.top + self.radius + 10;
var leftCornerX = field.left + self.radius + 10;
var rightCornerX = field.right - self.radius - 10;
var centerX = 2048 / 2;
var centerY = 2732 / 2;
// Check if player just entered top left corner
if (self.lastX > leftCornerX + cornerMargin && self.x <= leftCornerX + cornerMargin && self.lastY > topCornerY + cornerMargin && self.y <= topCornerY + cornerMargin) {
LK.showGameOver(); // Restart match automatically
return;
}
// Check if player just entered top right corner
if (self.lastX < rightCornerX - cornerMargin && self.x >= rightCornerX - cornerMargin && self.lastY > topCornerY + cornerMargin && self.y <= topCornerY + cornerMargin) {
LK.showGameOver(); // Restart match automatically
return;
}
if (!self.isUser) {
// AI logic for teamB only
if (self.team === 1) {
// Level 2'de AI daha hızlı ve daha iyi oynasın
var isLevel2 = !!self.level2;
// TeamB AI: ONLY attack user's goal (topGoal), never own goal
// If close to ball, move toward ball and try to shoot toward topGoal
var dx = ball.x - self.x;
var dy = ball.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Only try to kick toward topGoal (never own goal)
if (dist < (isLevel2 ? 180 : 120)) {
// Try to "kick" the ball toward topGoal if close enough
var goalDx = topGoal.x - ball.x;
var goalDy = topGoal.y - ball.y;
var goalDist = Math.sqrt(goalDx * goalDx + goalDy * goalDy);
if (goalDist > 0) {
// Simulate a kick if close enough to ball
if (dist < self.radius + ball.radius + 10) {
ball.vx += goalDx / goalDist * (isLevel2 ? 12 : 7); // Level 2: çok daha güçlü şut
ball.vy += goalDy / goalDist * (isLevel2 ? 12 : 7);
lastTeamTouched = 1;
}
}
// Move toward ball
self.x += dx / dist * (isLevel2 ? 16 : 9); // Level 2: çok daha hızlı hareket
self.y += dy / dist * (isLevel2 ? 16 : 9);
} else {
// Move toward a position between ball and topGoal (attack position)
var attackX = ball.x;
var attackY = ball.y + (isLevel2 ? 180 : 100);
var adx = attackX - self.x;
var ady = attackY - self.y;
var adist = Math.sqrt(adx * adx + ady * ady);
if (adist > 10) {
self.x += adx / adist * (isLevel2 ? 10 : 6); // Level 2: daha hızlı pozisyon alma
self.y += ady / adist * (isLevel2 ? 10 : 6);
}
}
}
}
// Clamp inside field (vertical orientation)
if (self.x < field.left + self.radius) self.x = field.left + self.radius;
if (self.x > field.right - self.radius) self.x = field.right - self.radius;
if (self.y < field.top + self.radius) self.y = field.top + self.radius;
if (self.y > field.bottom - self.radius) self.y = field.bottom - self.radius;
// Update lastX, lastY for next frame
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a8f3c,
// Football field green
fullscreen: true
});
/****
* Game Code
****/
// Tween plugin for animations (not used in MVP but included for future use)
// Field dimensions (full screen, no margins)
var field = {
width: 2048,
height: 2732,
left: 0,
right: 2048,
top: 0,
bottom: 2732
};
// Play background music continuously
LK.playMusic('2');
// Draw field (rectangle, lines, center circle, etc.)
var fieldAsset = LK.getAsset('field', {
width: field.width,
height: field.height,
color: 0x2e7d32,
// More realistic football field green
shape: 'box',
x: field.left,
y: field.top
});
game.addChild(fieldAsset);
// Center line (horizontal now)
var centerLine = LK.getAsset('centerLine', {
width: 10,
height: field.height,
color: 0xffffff,
shape: 'box',
x: field.left + field.width / 2 - 5,
y: field.top
});
game.addChild(centerLine);
// Penalty areas (top and bottom)
var penaltyWidth = 900;
var penaltyHeight = 300;
var topPenalty = LK.getAsset('penaltyAreaLeft', {
width: penaltyWidth,
height: penaltyHeight,
color: 0xffffff,
shape: 'box',
x: field.left + field.width / 2 - penaltyWidth / 2,
y: field.top - 5
});
topPenalty.alpha = 0.12;
game.addChild(topPenalty);
var bottomPenalty = LK.getAsset('penaltyAreaRight', {
width: penaltyWidth,
height: penaltyHeight,
color: 0xffffff,
shape: 'box',
x: field.left + field.width / 2 - penaltyWidth / 2,
y: field.bottom - penaltyHeight + 5
});
bottomPenalty.alpha = 0.12;
game.addChild(bottomPenalty);
// Goal areas (top and bottom)
var goalAreaWidth = 500;
var goalAreaHeight = 180;
var topGoalArea = LK.getAsset('goalAreaLeft', {
width: goalAreaWidth,
height: goalAreaHeight,
color: 0xffffff,
shape: 'box',
x: field.left + field.width / 2 - goalAreaWidth / 2,
y: field.top - 5
});
topGoalArea.alpha = 0.18;
game.addChild(topGoalArea);
var bottomGoalArea = LK.getAsset('goalAreaRight', {
width: goalAreaWidth,
height: goalAreaHeight,
color: 0xffffff,
shape: 'box',
x: field.left + field.width / 2 - goalAreaWidth / 2,
y: field.bottom - goalAreaHeight + 5
});
bottomGoalArea.alpha = 0.18;
game.addChild(bottomGoalArea);
// Penalty spots
var penaltySpotRadius = 18;
var topPenaltySpot = LK.getAsset('penaltySpotLeft', {
width: penaltySpotRadius * 2,
height: penaltySpotRadius * 2,
color: 0xffffff,
shape: 'ellipse',
x: field.left + field.width / 2 - penaltySpotRadius,
y: field.top + 120
});
topPenaltySpot.alpha = 0.7;
game.addChild(topPenaltySpot);
var bottomPenaltySpot = LK.getAsset('penaltySpotRight', {
width: penaltySpotRadius * 2,
height: penaltySpotRadius * 2,
color: 0xffffff,
shape: 'ellipse',
x: field.left + field.width / 2 - penaltySpotRadius,
y: field.bottom - 120 - penaltySpotRadius * 2
});
bottomPenaltySpot.alpha = 0.7;
game.addChild(bottomPenaltySpot);
// Center circle
var centerCircle = LK.getAsset('centerCircle', {
width: 320,
height: 320,
color: 0xffffff,
shape: 'ellipse',
x: field.left + field.width / 2 - 160,
y: field.top + field.height / 2 - 160
});
centerCircle.alpha = 0.25;
game.addChild(centerCircle);
// Center spot
var centerSpot = LK.getAsset('centerSpot', {
width: 24,
height: 24,
color: 0xffffff,
shape: 'ellipse',
x: field.left + field.width / 2 - 12,
y: field.top + field.height / 2 - 12
});
centerSpot.alpha = 0.7;
game.addChild(centerSpot);
// Corner arcs (for visual, not used in logic)
for (var i = 0; i < 4; i++) {
var cx = i < 2 ? field.left : field.right;
var cy = i % 2 === 0 ? field.top : field.bottom;
var cornerArc = LK.getAsset('cornerArc' + i, {
width: 60,
height: 60,
color: 0xffffff,
shape: 'ellipse',
x: cx - 30,
y: cy - 30
});
cornerArc.alpha = 0.15;
game.addChild(cornerArc);
}
// Goals (top and bottom)
var goalWidth = 400;
var goalHeight = 120;
var topGoal = new Goal('goalTop');
var bottomGoal = new Goal('goalBottom');
topGoal.x = field.left + field.width / 2;
topGoal.y = field.top - 20 + goalHeight / 2;
bottomGoal.x = field.left + field.width / 2;
bottomGoal.y = field.bottom + 20 - goalHeight / 2;
topGoal.width = goalWidth;
topGoal.height = goalHeight;
bottomGoal.width = goalWidth;
bottomGoal.height = goalHeight;
game.addChild(topGoal);
game.addChild(bottomGoal);
// Ball
var ball = new Ball();
ball.x = field.left + field.width / 2;
ball.y = field.top + field.height / 2;
var ballAsset = ball.children[0];
// Make the ball slightly smaller
ballAsset.width = 100;
ballAsset.height = 100;
ball.radius = 50;
ballAsset.color = 0xffffff;
game.addChild(ball);
// Teams
var teamA = [];
var teamB = [];
var playerRadius = 90;
var playerColors = [0x1e90ff, 0xff3333]; // Blue, Red
// Add goalkeeper for teamA (top)
var keeperA = new Goalkeeper();
keeperA.setTeam(0);
keeperA.x = topGoal.x;
keeperA.y = topGoal.y + 10;
game.addChild(keeperA);
// Place teamA (top, blue) - only 1 player
for (var i = 0; i < 1; i++) {
var p = new Player();
var asset = p.children[0];
asset.width = playerRadius * 2 * 1.2;
asset.height = playerRadius * 2 * 1.2;
asset.color = playerColors[0];
p.radius = playerRadius * 1.2;
p.team = 0;
p.index = i;
// Place at slightly left of center (Messi)
p.x = field.left + field.width / 2 - 220;
p.y = field.top + 400;
// User-controlled
p.isUser = true;
teamA.push(p);
game.addChild(p);
}
// Add goalkeeper for teamB (bottom)
var keeperB = new Goalkeeper();
keeperB.setTeam(1);
keeperB.x = bottomGoal.x;
keeperB.y = bottomGoal.y - 10;
game.addChild(keeperB);
// Place teamB (bottom, red) - only 1 player
for (var i = 0; i < 1; i++) {
var p = new Player();
// Replace default asset with teamB asset
p.removeChild(p.children[0]);
var asset = p.attachAsset('playerB', {
anchorX: 0.5,
anchorY: 0.5
});
asset.width = playerRadius * 2 * 1.2;
asset.height = playerRadius * 2 * 1.2;
asset.color = playerColors[1];
p.radius = playerRadius * 1.2;
p.team = 1;
p.index = i;
// Place at slightly right of center (Ronaldo)
p.x = field.left + field.width / 2 + 220;
p.y = field.bottom - 400;
p.isUser = false; // AI
teamB.push(p);
game.addChild(p);
}
// Score
var scoreA = 0;
var scoreB = 0;
var scoreTxt = new Text2('0 - 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// GOAL! text (hidden by default)
var goalText = new Text2('GOAL!', {
size: 220,
fill: 0xFFD700,
font: "Impact, Arial Black, Tahoma"
});
goalText.anchor.set(0.5, 0.5);
goalText.visible = false;
LK.gui.center.addChild(goalText);
// Helper: show GOAL! text for a short time
function showGoalText() {
goalText.visible = true;
goalText.alpha = 1;
// Hide after 1 second
LK.setTimeout(function () {
goalText.visible = false;
goalText.alpha = 1;
}, 1000);
}
// Game state
var lastTouch = {
x: 0,
y: 0
};
var draggingPlayer = null;
var throwInActive = false;
var throwInTeam = 0;
var throwInPos = {
x: 0,
y: 0
};
var cornerActive = false;
var cornerTeam = 0;
var cornerPos = {
x: 0,
y: 0
};
var lastTeamTouched = 0; // 0: teamA, 1: teamB
// Helper: check collision between two circles
function circlesCollide(ax, ay, ar, bx, by, br) {
var dx = ax - bx;
var dy = ay - by;
var dist = Math.sqrt(dx * dx + dy * dy);
return dist < ar + br;
}
// Helper: check if ball is in goal
function isGoal(ball, goal) {
return ball.y > goal.y - goal.height / 2 && ball.y < goal.y + goal.height / 2 && ball.x > goal.x - goal.width / 2 && ball.x < goal.x + goal.width / 2;
}
// Helper: reset positions after goal
function resetPositions() {
// Ball to center
ball.x = field.left + field.width / 2;
ball.y = field.top + field.height / 2;
ball.vx = 0;
ball.vy = 0;
// TeamA (top)
for (var i = 0; i < 1; i++) {
var p = teamA[i];
p.x = field.left + field.width / 2 - 220;
p.y = field.top + 400;
p.radius = playerRadius * 1.2;
}
// TeamB (bottom)
for (var i = 0; i < 1; i++) {
var p = teamB[i];
p.x = field.left + field.width / 2 + 220;
p.y = field.bottom - 400;
p.radius = playerRadius * 1.2;
}
// Reset goalkeepers
keeperA.x = topGoal.x;
keeperA.y = topGoal.y + 10;
keeperB.x = bottomGoal.x;
keeperB.y = bottomGoal.y - 10;
}
// Helper: check if ball is out for throw-in or corner
function checkOutOfBounds() {
// Top/bottom (taç)
if (ball.y < field.top) {
throwInActive = true;
throwInTeam = 1; // Bottom team gets throw-in
throwInPos.y = field.top + ball.radius + 10;
throwInPos.x = Math.max(field.left + ball.radius + 10, Math.min(ball.x, field.right - ball.radius - 10));
ball.vx = 0;
ball.vy = 0;
ball.y = throwInPos.y;
ball.x = throwInPos.x;
} else if (ball.y > field.bottom) {
throwInActive = true;
throwInTeam = 0; // Top team gets throw-in
throwInPos.y = field.bottom - ball.radius - 10;
throwInPos.x = Math.max(field.left + ball.radius + 10, Math.min(ball.x, field.right - ball.radius - 10));
ball.vx = 0;
ball.vy = 0;
ball.y = throwInPos.y;
ball.x = throwInPos.x;
}
// Left/right (korner veya aut)
else if (ball.x < field.left) {
// If ball is between goal posts, it's a goal
if (ball.y > topGoal.y - topGoal.height / 2 && ball.y < topGoal.y + topGoal.height / 2) {
// Top goal
scoreB++;
scoreTxt.setText(scoreA + " - " + scoreB);
showGoalText();
resetPositions();
return;
}
// Otherwise, corner or goal kick
if (ball.y < field.top + 200) {
// Top left corner
cornerActive = true;
cornerTeam = 1; // Bottom team gets corner
cornerPos.x = field.left + 30;
cornerPos.y = field.top + 30;
} else if (ball.y > field.bottom - 200) {
// Bottom left corner
cornerActive = true;
cornerTeam = 0; // Top team gets corner
cornerPos.x = field.left + 30;
cornerPos.y = field.bottom - 30;
} else {
// Goal kick (not implemented, treat as throw-in for now)
throwInActive = true;
throwInTeam = lastTeamTouched === 0 ? 1 : 0;
throwInPos.y = Math.max(field.top + ball.radius + 10, Math.min(ball.y, field.bottom - ball.radius - 10));
throwInPos.x = field.left + ball.radius + 10;
}
ball.vx = 0;
ball.vy = 0;
if (cornerActive) {
ball.x = cornerPos.x;
ball.y = cornerPos.y;
} else {
ball.x = throwInPos.x;
ball.y = throwInPos.y;
}
} else if (ball.x > field.right) {
// If ball is between goal posts, it's a goal
if (ball.y > bottomGoal.y - bottomGoal.height / 2 && ball.y < bottomGoal.y + bottomGoal.height / 2) {
// Bottom goal
scoreA++;
scoreTxt.setText(scoreA + " - " + scoreB);
showGoalText();
resetPositions();
return;
}
// Otherwise, corner or goal kick
if (ball.y < field.top + 200) {
// Top right corner
cornerActive = true;
cornerTeam = 1; // Bottom team gets corner
cornerPos.x = field.right - 30;
cornerPos.y = field.top + 30;
} else if (ball.y > field.bottom - 200) {
// Bottom right corner
cornerActive = true;
cornerTeam = 0; // Top team gets corner
cornerPos.x = field.right - 30;
cornerPos.y = field.bottom - 30;
} else {
// Goal kick (not implemented, treat as throw-in for now)
throwInActive = true;
throwInTeam = lastTeamTouched === 0 ? 1 : 0;
throwInPos.y = Math.max(field.top + ball.radius + 10, Math.min(ball.y, field.bottom - ball.radius - 10));
throwInPos.x = field.right - ball.radius - 10;
}
ball.vx = 0;
ball.vy = 0;
if (cornerActive) {
ball.x = cornerPos.x;
ball.y = cornerPos.y;
} else {
ball.x = throwInPos.x;
ball.y = throwInPos.y;
}
}
}
// Touch/drag logic for user player
game.down = function (x, y, obj) {
// Only allow drag if not in throw-in/corner
if (throwInActive || cornerActive) return;
// Check if any user player is touched (all teamA)
for (var i = 0; i < teamA.length; i++) {
var userPlayer = teamA[i];
var dx = x - userPlayer.x;
var dy = y - userPlayer.y;
if (dx * dx + dy * dy < userPlayer.radius * userPlayer.radius) {
draggingPlayer = userPlayer;
draggingPlayer.isDragging = true;
lastTouch.x = x;
lastTouch.y = y;
break;
}
}
};
game.move = function (x, y, obj) {
if (draggingPlayer && draggingPlayer.isDragging) {
// Move player with finger, clamp inside field (vertical)
draggingPlayer.x = Math.max(field.left + draggingPlayer.radius, Math.min(x, field.right - draggingPlayer.radius));
draggingPlayer.y = Math.max(field.top + draggingPlayer.radius, Math.min(y, field.bottom - draggingPlayer.radius));
lastTouch.x = x;
lastTouch.y = y;
}
};
game.up = function (x, y, obj) {
if (draggingPlayer && draggingPlayer.isDragging) {
// On release, if close to ball, kick it
var dx = ball.x - draggingPlayer.x;
var dy = ball.y - draggingPlayer.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < draggingPlayer.radius + ball.radius + 10) {
// Kick direction: from player to ball, magnitude based on drag
var kickVx = (ball.x - lastTouch.x) * 0.3;
var kickVy = (ball.y - lastTouch.y) * 0.3;
ball.vx += kickVx;
ball.vy += kickVy;
lastTeamTouched = 0;
}
draggingPlayer.isDragging = false;
draggingPlayer = null;
}
// Throw-in/corner logic
if (throwInActive) {
// Only allow throw-in by correct team
if (throwInTeam === 0) {
// Left team
var dx = x - ball.x;
var dy = y - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 30) {
ball.vx = dx * 0.15;
ball.vy = dy * 0.15;
throwInActive = false;
}
}
if (throwInTeam === 1) {
// Right team
var dx = x - ball.x;
var dy = y - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 30) {
ball.vx = dx * 0.15;
ball.vy = dy * 0.15;
throwInActive = false;
}
}
}
if (cornerActive) {
// Only allow corner by correct team
if (cornerTeam === 0) {
// Left team
var dx = x - ball.x;
var dy = y - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 30) {
ball.vx = dx * 0.15;
ball.vy = dy * 0.15;
cornerActive = false;
}
}
if (cornerTeam === 1) {
// Right team
var dx = x - ball.x;
var dy = y - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 30) {
ball.vx = dx * 0.15;
ball.vy = dy * 0.15;
cornerActive = false;
}
}
}
};
// Main game update
game.update = function () {
// Update goalkeepers
keeperA.update();
keeperB.update();
// Update all players
for (var i = 0; i < 1; i++) {
teamA[i].update();
teamB[i].update();
}
// Update ball
ball.update();
// Ball-player collision
for (var i = 0; i < 1; i++) {
var p = teamA[i];
var dx = ball.x - p.x;
var dy = ball.y - p.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < ball.radius + p.radius) {
// Push ball away
var overlap = ball.radius + p.radius - dist + 1;
var nx = dx / dist;
var ny = dy / dist;
ball.x += nx * overlap;
ball.y += ny * overlap;
// Ball velocity: if user player, shoot fast!
if (p.isUser) {
// Shoot with high speed in the direction from player to ball
var shootPower = 18;
ball.vx = nx * shootPower;
ball.vy = ny * shootPower;
} else {
ball.vx += nx * 2;
ball.vy += ny * 2;
}
lastTeamTouched = 0;
}
var p2 = teamB[i];
dx = ball.x - p2.x;
dy = ball.y - p2.y;
dist = Math.sqrt(dx * dx + dy * dy);
if (dist < ball.radius + p2.radius) {
var overlap = ball.radius + p2.radius - dist + 1;
var nx = dx / dist;
var ny = dy / dist;
ball.x += nx * overlap;
ball.y += ny * overlap;
ball.vx += nx * 2;
ball.vy += ny * 2;
lastTeamTouched = 1;
}
}
// Ball-wall collision (field boundaries)
// --- Korner invisible wall logic ---
// Define korner (corner) area size
var kornerMargin = 120; // px from each edge (adjust as needed)
var centerX = field.left + field.width / 2;
var centerY = field.top + field.height / 2;
// Top left korner
if (ball.x < field.left + kornerMargin && ball.y < field.top + kornerMargin) {
// Slide ball toward center
var dx = centerX - ball.x;
var dy = centerY - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var slideSpeed = 12;
ball.vx = dx / dist * slideSpeed;
ball.vy = dy / dist * slideSpeed;
// Move ball slightly out of the corner to avoid repeated triggers
ball.x = field.left + kornerMargin + ball.radius;
ball.y = field.top + kornerMargin + ball.radius;
}
}
// Top right korner
if (ball.x > field.right - kornerMargin && ball.y < field.top + kornerMargin) {
var dx = centerX - ball.x;
var dy = centerY - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var slideSpeed = 12;
ball.vx = dx / dist * slideSpeed;
ball.vy = dy / dist * slideSpeed;
ball.x = field.right - kornerMargin - ball.radius;
ball.y = field.top + kornerMargin + ball.radius;
}
}
// Bottom left korner
if (ball.x < field.left + kornerMargin && ball.y > field.bottom - kornerMargin) {
var dx = centerX - ball.x;
var dy = centerY - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var slideSpeed = 12;
ball.vx = dx / dist * slideSpeed;
ball.vy = dy / dist * slideSpeed;
ball.x = field.left + kornerMargin + ball.radius;
ball.y = field.bottom - kornerMargin - ball.radius;
}
}
// Bottom right korner
if (ball.x > field.right - kornerMargin && ball.y > field.bottom - kornerMargin) {
var dx = centerX - ball.x;
var dy = centerY - ball.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
var slideSpeed = 12;
ball.vx = dx / dist * slideSpeed;
ball.vy = dy / dist * slideSpeed;
ball.x = field.right - kornerMargin - ball.radius;
ball.y = field.bottom - kornerMargin - ball.radius;
}
}
// Standard wall collision (field boundaries)
if (ball.x < field.left + ball.radius) {
ball.x = field.left + ball.radius;
ball.vx = -ball.vx * 0.7;
}
if (ball.x > field.right - ball.radius) {
ball.x = field.right - ball.radius;
ball.vx = -ball.vx * 0.7;
}
if (ball.y < field.top + ball.radius) {
ball.y = field.top + ball.radius;
ball.vy = -ball.vy * 0.7;
}
if (ball.y > field.bottom - ball.radius) {
ball.y = field.bottom - ball.radius;
ball.vy = -ball.vy * 0.7;
}
// Check for goals
if (isGoal(ball, topGoal)) {
scoreB++;
scoreTxt.setText(scoreA + " - " + scoreB);
showGoalText();
resetPositions();
return;
}
if (isGoal(ball, bottomGoal)) {
scoreA++;
scoreTxt.setText(scoreA + " - " + scoreB);
showGoalText();
resetPositions();
return;
}
// Check for throw-in/corner
if (!throwInActive && !cornerActive) {
checkOutOfBounds();
}
// Win condition (first to 5 or 10, level system)
if (typeof gameLevel === "undefined") gameLevel = 1;
if (typeof level2Inited === "undefined") level2Inited = false;
// Level 1: 5 gole ilk ulaşan kazanır, Level 2: 10 gole ilk ulaşan kazanır
if (gameLevel === 1) {
if (scoreA >= 5) {
// Level 1 kazanıldı, Level 2 başlat
gameLevel = 2;
level2Inited = false;
// Skorları sıfırla, pozisyonları sıfırla, GOAL! yazısı gösterme
scoreA = 0;
scoreB = 0;
scoreTxt.setText(scoreA + " - " + scoreB);
resetPositions();
// Level 2 başlatıldığında AI hızını artırmak için flag
level2Inited = false;
// Kısa bir "Level 2" yazısı göster
if (typeof levelText === "undefined") {
levelText = new Text2('NOW Angry Messi !!!', {
size: 180,
fill: 0xFF0000,
// Kırmızı renk
font: "Impact, Arial Black, Tahoma"
});
levelText.anchor.set(0.5, 0.5);
// Place Angry Messi just below GOAL! text
// GOAL! text is centered at gui.center, so we offset Y by its height + margin
// Use goalText.height if available, otherwise use a fixed offset
var goalTextOffset = (goalText && goalText.height ? goalText.height : 220) / 2;
levelText.y = goalText.y + goalTextOffset + 80; // 80px margin below GOAL!
LK.gui.center.addChild(levelText);
}
levelText.visible = true;
levelText.alpha = 1;
LK.setTimeout(function () {
levelText.visible = false;
}, 3000); // 3 saniye göster
return;
}
if (scoreB >= 5) {
LK.showGameOver();
return;
}
} else if (gameLevel === 2) {
// Level 2'de AI daha hızlı ve daha iyi oynasın
if (!level2Inited) {
// AI hız ve zorluk parametrelerini artır
// teamB AI için parametreleri güncelle
for (var i = 0; i < teamB.length; i++) {
var p = teamB[i];
p.level2 = true; // AI update fonksiyonunda kontrol edilecek
}
// Kaleci refleksini de artır
keeperB.level2 = true;
level2Inited = true;
}
if (scoreA >= 10) {
LK.showYouWin();
return;
}
if (scoreB >= 10) {
LK.showGameOver();
return;
}
}
};