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