/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Football (Top) class var Ball = Container.expand(function () { var self = Container.call(this); // Attach football asset (ellipse, white) var ballAsset = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); // Ball state self.isMoving = false; self.vx = 0; self.vy = 0; // Ball radius for collision self.radius = ballAsset.width / 2; // Ball update: move if in motion self.update = function () { if (self.isMoving) { self.x += self.vx; self.y += self.vy; // Friction self.vx *= 0.98; self.vy *= 0.98; // Prevent ball from leaving left/right boundaries if (self.x - self.radius < 0) { self.x = self.radius; self.vx = -self.vx * 0.7; } if (self.x + self.radius > 2048) { self.x = 2048 - self.radius; self.vx = -self.vx * 0.7; } // Prevent ball from leaving top/bottom boundaries if (self.y - self.radius < 0) { self.y = self.radius; self.vy = -self.vy * 0.7; } if (self.y + self.radius > 2732) { self.y = 2732 - self.radius; self.vy = -self.vy * 0.7; } // Stop if slow enough if (Math.abs(self.vx) < 1 && Math.abs(self.vy) < 1) { self.vx = 0; self.vy = 0; self.isMoving = false; } } }; // Reset ball to initial position self.reset = function (x, y) { self.x = x; self.y = y; self.vx = 0; self.vy = 0; self.isMoving = false; }; return self; }); // Goal (Kale) class var Goal = Container.expand(function () { var self = Container.call(this); // Attach goal asset (rectangle, yellow) var goalAsset = self.attachAsset('goal', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Goalkeeper (Kaleci) class var Goalkeeper = Container.expand(function () { var self = Container.call(this); // Attach goalkeeper asset (rectangle, blue) var keeperAsset = self.attachAsset('goalkeeper', { anchorX: 0.5, anchorY: 0.5 }); // Movement bounds self.minX = 0; self.maxX = 2048; self.y = 420; // Just in front of goal // Speed self.speed = 18; // Increased speed for faster goalkeeper // Target x (where to move) self.targetX = 1024; // Update: move towards targetX self.update = function () { if (Math.abs(self.x - self.targetX) > self.speed) { if (self.x < self.targetX) { self.x += self.speed; } else { self.x -= self.speed; } } else { self.x = self.targetX; } // Clamp if (self.x < self.minX + keeperAsset.width / 2) self.x = self.minX + keeperAsset.width / 2; if (self.x > self.maxX - keeperAsset.width / 2) self.x = self.maxX - keeperAsset.width / 2; }; // Set target x self.moveTo = function (x) { self.targetX = x; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a8f3c // Green football field }); /**** * Game Code ****/ // --- Asset Initialization --- // --- Game Variables --- var score = 0; var maxGoals = 5; var timeLimit = 120; // seconds (2 minutes) var timeLeft = timeLimit; var dragging = false; var dragStart = { x: 0, y: 0 }; var dragBallStart = { x: 0, y: 0 }; var shotInProgress = false; var lastGoal = false; var gameEnded = false; // --- Create Game Elements --- // Goal var goal = new Goal(); goal.x = 1024; goal.y = 200; game.addChild(goal); // Goalkeeper var goalkeeper = new Goalkeeper(); goalkeeper.x = 1024; // Place goalkeeper just in front of the goal (align y with goal's bottom edge) goalkeeper.y = goal.y + goal.children[0].height / 2 + goalkeeper.children[0].height / 2 - 10; game.addChild(goalkeeper); // Ball var ball = new Ball(); ball.reset(1024, 2000); game.addChild(ball); // --- Score Display --- var timerTxt = new Text2('Süre: ' + timeLeft, { size: 90, fill: 0xFFFFFF }); timerTxt.anchor.set(1, 0); // Anchor right-top timerTxt.x = 0; timerTxt.y = 0; // Timer will be positioned at the far right of the top GUI var scoreTxt = new Text2('Gol: 0', { size: 120, fill: 0xFFF700 }); scoreTxt.anchor.set(0, 0); // Anchor left-top scoreTxt.x = 0; scoreTxt.y = 0; LK.gui.topLeft.addChild(scoreTxt); // Place timerTxt at the far right of the top GUI timerTxt.x = 0; timerTxt.y = 0; LK.gui.topRight.addChild(timerTxt); // --- Helper: Check if ball is in goal --- function isGoal(ball) { // Ball must cross the goal line (y < goal.y + goal height/2) // and x within goal width var goalTop = goal.y - goal.children[0].height / 2; var goalLeft = goal.x - goal.children[0].width / 2; var goalRight = goal.x + goal.children[0].width / 2; return ball.y - ball.radius < goalTop && ball.x > goalLeft && ball.x < goalRight; } // --- Helper: Check collision with goalkeeper --- function isSaved(ball, goalkeeper) { // Simple AABB collision var keeper = goalkeeper.children[0]; var keeperLeft = goalkeeper.x - keeper.width / 2; var keeperRight = goalkeeper.x + keeper.width / 2; var keeperTop = goalkeeper.y - keeper.height / 2; var keeperBottom = goalkeeper.y + keeper.height / 2; var ballLeft = ball.x - ball.radius; var ballRight = ball.x + ball.radius; var ballTop = ball.y - ball.radius; var ballBottom = ball.y + ball.radius; return ballRight > keeperLeft && ballLeft < keeperRight && ballBottom > keeperTop && ballTop < keeperBottom; } // --- Helper: Reset ball position --- function resetBall() { ball.reset(1024, 2000); dragging = false; shotInProgress = false; } // --- Helper: End Game --- function endGame(win) { gameEnded = true; if (win) { LK.showYouWin(); } else { LK.showGameOver(); } } // --- Timer --- var timerInterval = LK.setInterval(function () { if (gameEnded) return; timeLeft--; if (timeLeft < 0) timeLeft = 0; timerTxt.setText('Süre: ' + timeLeft); if (timeLeft === 0) { endGame(false); LK.clearInterval(timerInterval); } }, 1000); // --- Drag & Shoot Mechanics --- game.down = function (x, y, obj) { if (gameEnded) return; // Only allow drag if ball is not moving and touch is on ball var dx = x - ball.x; var dy = y - ball.y; if (!ball.isMoving && dx * dx + dy * dy < ball.radius * ball.radius * 1.2) { dragging = true; dragStart.x = x; dragStart.y = y; dragBallStart.x = ball.x; dragBallStart.y = ball.y; } }; game.move = function (x, y, obj) { if (gameEnded) return; if (dragging && !ball.isMoving) { // Move ball with finger, allow anywhere on the field (no clamp) var nx = dragBallStart.x + (x - dragStart.x); var ny = dragBallStart.y + (y - dragStart.y); // Optionally, keep ball inside visible area if (nx < ball.radius) nx = ball.radius; if (nx > 2048 - ball.radius) nx = 2048 - ball.radius; if (ny < ball.radius) ny = ball.radius; if (ny > 2732 - ball.radius) ny = 2732 - ball.radius; ball.x = nx; ball.y = ny; } }; game.up = function (x, y, obj) { if (gameEnded) return; if (dragging && !ball.isMoving) { // Calculate velocity based on drag var dx = dragStart.x - x; var dy = dragStart.y - y; // Only shoot if drag is upwards and long enough if (dy > 80) { // Normalize and scale var power = Math.sqrt(dx * dx + dy * dy); var maxPower = 1200; if (power > maxPower) power = maxPower; var scale = 64 * (power / maxPower); // Increased from 32 to 64 for higher speed ball.vx = -dx / power * scale; ball.vy = -dy / power * scale; ball.isMoving = true; shotInProgress = true; } } dragging = false; }; // --- Main Game Update --- game.update = function () { if (gameEnded) return; // Ball update ball.update(); // Goalkeeper AI: track ball if shot in progress, else random idle if (shotInProgress && ball.isMoving) { // Predict where ball will cross keeper's y var t = (goalkeeper.y - ball.y) / ball.vy; var predictedX = ball.x + ball.vx * t; if (t > 0 && t < 60) { goalkeeper.moveTo(predictedX); } } else { // Idle: move to center slowly goalkeeper.moveTo(1024); } goalkeeper.update(); // Check for goal or save if (shotInProgress && ball.isMoving) { // Save // Kalecinin bazen topu kaçırması için rastgele bir şans ekle var keeperSaveChance = 0.35; // %35 ihtimalle kurtarır, %65 gol olur if (isSaved(ball, goalkeeper) && Math.random() < keeperSaveChance) { shotInProgress = false; // Play ungol sound when goalkeeper saves LK.getSound('ungol').play(); // Flash keeper LK.effects.flashObject(goalkeeper, 0x00ffff, 400); // Ball bounces back, but if the keeper is 'sweet' (şeker), kick the ball forward // Let's define 'şeker' as a random chance for now (e.g. 40% of the time) if (Math.random() < 0.4) { // Kaleci şeker: topa vuruyor! // Ball is kicked forward with a random angle and speed var angle = (Math.random() - 0.5) * Math.PI / 2 + Math.PI / 2; // between 45 and 135 degrees var speed = 40 + Math.random() * 30; ball.vx = Math.cos(angle) * speed; ball.vy = Math.sin(angle) * speed; ball.isMoving = true; // No reset, player can chase the ball again! } else { // Ball bounces back as before ball.vy = Math.abs(ball.vy) * 0.5; ball.vx = ball.vx * 0.5; ball.isMoving = true; // After bounce, reset after short delay LK.setTimeout(function () { resetBall(); }, 700); } } // Goal else if (isGoal(ball)) { shotInProgress = false; score++; scoreTxt.setText('Gol: ' + score); // Play goal sound LK.getSound('goll').play(); LK.effects.flashScreen(0x00ff00, 400); // Animate ball into net tween(ball, { y: goal.y - 80 }, { duration: 250, easing: tween.cubicOut, onFinish: function onFinish() { resetBall(); } }); // Win condition if (score >= maxGoals) { endGame(true); LK.clearInterval(timerInterval); } } // Yan duvarlara çarpınca top seksin, dışarı çıkmasın else if (ball.x - ball.radius < 0) { ball.x = ball.radius; ball.vx = -ball.vx * 0.7; // Damping for realism // Top köşeden kaleye yönlendirilsin if (ball.y < goal.y + goal.children[0].height / 2 + 40) { // Top üst köşede ise, kaleye doğru yönlendir ball.vy = -Math.abs(ball.vy) * 0.8; ball.vx = Math.abs(ball.vx) * 0.7; } } else if (ball.x + ball.radius > 2048) { ball.x = 2048 - ball.radius; ball.vx = -ball.vx * 0.7; if (ball.y < goal.y + goal.children[0].height / 2 + 40) { ball.vy = -Math.abs(ball.vy) * 0.8; ball.vx = -Math.abs(ball.vx) * 0.7; } // Ball never leaves the field now; no reset needed for out-of-bounds } // If the shot is in progress, the ball is not moving anymore, and it's not a goal or save, play ungol sound if (shotInProgress && !ball.isMoving) { // Not a goal, not a save, and the ball stopped: missed shot LK.getSound('ungol').play(); shotInProgress = false; // Optionally, reset the ball after a short delay for user feedback LK.setTimeout(function () { resetBall(); }, 700); } } }; // --- Playfield layout notes --- // Goal: y = 200 // Goalkeeper: y = 310 // Ball: y = 2000 (start) // All elements centered horizontally // --- Music, sound, etc. are omitted as per guidelines ---
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Football (Top) class
var Ball = Container.expand(function () {
var self = Container.call(this);
// Attach football asset (ellipse, white)
var ballAsset = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
// Ball state
self.isMoving = false;
self.vx = 0;
self.vy = 0;
// Ball radius for collision
self.radius = ballAsset.width / 2;
// Ball update: move if in motion
self.update = function () {
if (self.isMoving) {
self.x += self.vx;
self.y += self.vy;
// Friction
self.vx *= 0.98;
self.vy *= 0.98;
// Prevent ball from leaving left/right boundaries
if (self.x - self.radius < 0) {
self.x = self.radius;
self.vx = -self.vx * 0.7;
}
if (self.x + self.radius > 2048) {
self.x = 2048 - self.radius;
self.vx = -self.vx * 0.7;
}
// Prevent ball from leaving top/bottom boundaries
if (self.y - self.radius < 0) {
self.y = self.radius;
self.vy = -self.vy * 0.7;
}
if (self.y + self.radius > 2732) {
self.y = 2732 - self.radius;
self.vy = -self.vy * 0.7;
}
// Stop if slow enough
if (Math.abs(self.vx) < 1 && Math.abs(self.vy) < 1) {
self.vx = 0;
self.vy = 0;
self.isMoving = false;
}
}
};
// Reset ball to initial position
self.reset = function (x, y) {
self.x = x;
self.y = y;
self.vx = 0;
self.vy = 0;
self.isMoving = false;
};
return self;
});
// Goal (Kale) class
var Goal = Container.expand(function () {
var self = Container.call(this);
// Attach goal asset (rectangle, yellow)
var goalAsset = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Goalkeeper (Kaleci) class
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
// Attach goalkeeper asset (rectangle, blue)
var keeperAsset = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement bounds
self.minX = 0;
self.maxX = 2048;
self.y = 420; // Just in front of goal
// Speed
self.speed = 18; // Increased speed for faster goalkeeper
// Target x (where to move)
self.targetX = 1024;
// Update: move towards targetX
self.update = function () {
if (Math.abs(self.x - self.targetX) > self.speed) {
if (self.x < self.targetX) {
self.x += self.speed;
} else {
self.x -= self.speed;
}
} else {
self.x = self.targetX;
}
// Clamp
if (self.x < self.minX + keeperAsset.width / 2) self.x = self.minX + keeperAsset.width / 2;
if (self.x > self.maxX - keeperAsset.width / 2) self.x = self.maxX - keeperAsset.width / 2;
};
// Set target x
self.moveTo = function (x) {
self.targetX = x;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a8f3c // Green football field
});
/****
* Game Code
****/
// --- Asset Initialization ---
// --- Game Variables ---
var score = 0;
var maxGoals = 5;
var timeLimit = 120; // seconds (2 minutes)
var timeLeft = timeLimit;
var dragging = false;
var dragStart = {
x: 0,
y: 0
};
var dragBallStart = {
x: 0,
y: 0
};
var shotInProgress = false;
var lastGoal = false;
var gameEnded = false;
// --- Create Game Elements ---
// Goal
var goal = new Goal();
goal.x = 1024;
goal.y = 200;
game.addChild(goal);
// Goalkeeper
var goalkeeper = new Goalkeeper();
goalkeeper.x = 1024;
// Place goalkeeper just in front of the goal (align y with goal's bottom edge)
goalkeeper.y = goal.y + goal.children[0].height / 2 + goalkeeper.children[0].height / 2 - 10;
game.addChild(goalkeeper);
// Ball
var ball = new Ball();
ball.reset(1024, 2000);
game.addChild(ball);
// --- Score Display ---
var timerTxt = new Text2('Süre: ' + timeLeft, {
size: 90,
fill: 0xFFFFFF
});
timerTxt.anchor.set(1, 0); // Anchor right-top
timerTxt.x = 0;
timerTxt.y = 0;
// Timer will be positioned at the far right of the top GUI
var scoreTxt = new Text2('Gol: 0', {
size: 120,
fill: 0xFFF700
});
scoreTxt.anchor.set(0, 0); // Anchor left-top
scoreTxt.x = 0;
scoreTxt.y = 0;
LK.gui.topLeft.addChild(scoreTxt);
// Place timerTxt at the far right of the top GUI
timerTxt.x = 0;
timerTxt.y = 0;
LK.gui.topRight.addChild(timerTxt);
// --- Helper: Check if ball is in goal ---
function isGoal(ball) {
// Ball must cross the goal line (y < goal.y + goal height/2)
// and x within goal width
var goalTop = goal.y - goal.children[0].height / 2;
var goalLeft = goal.x - goal.children[0].width / 2;
var goalRight = goal.x + goal.children[0].width / 2;
return ball.y - ball.radius < goalTop && ball.x > goalLeft && ball.x < goalRight;
}
// --- Helper: Check collision with goalkeeper ---
function isSaved(ball, goalkeeper) {
// Simple AABB collision
var keeper = goalkeeper.children[0];
var keeperLeft = goalkeeper.x - keeper.width / 2;
var keeperRight = goalkeeper.x + keeper.width / 2;
var keeperTop = goalkeeper.y - keeper.height / 2;
var keeperBottom = goalkeeper.y + keeper.height / 2;
var ballLeft = ball.x - ball.radius;
var ballRight = ball.x + ball.radius;
var ballTop = ball.y - ball.radius;
var ballBottom = ball.y + ball.radius;
return ballRight > keeperLeft && ballLeft < keeperRight && ballBottom > keeperTop && ballTop < keeperBottom;
}
// --- Helper: Reset ball position ---
function resetBall() {
ball.reset(1024, 2000);
dragging = false;
shotInProgress = false;
}
// --- Helper: End Game ---
function endGame(win) {
gameEnded = true;
if (win) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// --- Timer ---
var timerInterval = LK.setInterval(function () {
if (gameEnded) return;
timeLeft--;
if (timeLeft < 0) timeLeft = 0;
timerTxt.setText('Süre: ' + timeLeft);
if (timeLeft === 0) {
endGame(false);
LK.clearInterval(timerInterval);
}
}, 1000);
// --- Drag & Shoot Mechanics ---
game.down = function (x, y, obj) {
if (gameEnded) return;
// Only allow drag if ball is not moving and touch is on ball
var dx = x - ball.x;
var dy = y - ball.y;
if (!ball.isMoving && dx * dx + dy * dy < ball.radius * ball.radius * 1.2) {
dragging = true;
dragStart.x = x;
dragStart.y = y;
dragBallStart.x = ball.x;
dragBallStart.y = ball.y;
}
};
game.move = function (x, y, obj) {
if (gameEnded) return;
if (dragging && !ball.isMoving) {
// Move ball with finger, allow anywhere on the field (no clamp)
var nx = dragBallStart.x + (x - dragStart.x);
var ny = dragBallStart.y + (y - dragStart.y);
// Optionally, keep ball inside visible area
if (nx < ball.radius) nx = ball.radius;
if (nx > 2048 - ball.radius) nx = 2048 - ball.radius;
if (ny < ball.radius) ny = ball.radius;
if (ny > 2732 - ball.radius) ny = 2732 - ball.radius;
ball.x = nx;
ball.y = ny;
}
};
game.up = function (x, y, obj) {
if (gameEnded) return;
if (dragging && !ball.isMoving) {
// Calculate velocity based on drag
var dx = dragStart.x - x;
var dy = dragStart.y - y;
// Only shoot if drag is upwards and long enough
if (dy > 80) {
// Normalize and scale
var power = Math.sqrt(dx * dx + dy * dy);
var maxPower = 1200;
if (power > maxPower) power = maxPower;
var scale = 64 * (power / maxPower); // Increased from 32 to 64 for higher speed
ball.vx = -dx / power * scale;
ball.vy = -dy / power * scale;
ball.isMoving = true;
shotInProgress = true;
}
}
dragging = false;
};
// --- Main Game Update ---
game.update = function () {
if (gameEnded) return;
// Ball update
ball.update();
// Goalkeeper AI: track ball if shot in progress, else random idle
if (shotInProgress && ball.isMoving) {
// Predict where ball will cross keeper's y
var t = (goalkeeper.y - ball.y) / ball.vy;
var predictedX = ball.x + ball.vx * t;
if (t > 0 && t < 60) {
goalkeeper.moveTo(predictedX);
}
} else {
// Idle: move to center slowly
goalkeeper.moveTo(1024);
}
goalkeeper.update();
// Check for goal or save
if (shotInProgress && ball.isMoving) {
// Save
// Kalecinin bazen topu kaçırması için rastgele bir şans ekle
var keeperSaveChance = 0.35; // %35 ihtimalle kurtarır, %65 gol olur
if (isSaved(ball, goalkeeper) && Math.random() < keeperSaveChance) {
shotInProgress = false;
// Play ungol sound when goalkeeper saves
LK.getSound('ungol').play();
// Flash keeper
LK.effects.flashObject(goalkeeper, 0x00ffff, 400);
// Ball bounces back, but if the keeper is 'sweet' (şeker), kick the ball forward
// Let's define 'şeker' as a random chance for now (e.g. 40% of the time)
if (Math.random() < 0.4) {
// Kaleci şeker: topa vuruyor!
// Ball is kicked forward with a random angle and speed
var angle = (Math.random() - 0.5) * Math.PI / 2 + Math.PI / 2; // between 45 and 135 degrees
var speed = 40 + Math.random() * 30;
ball.vx = Math.cos(angle) * speed;
ball.vy = Math.sin(angle) * speed;
ball.isMoving = true;
// No reset, player can chase the ball again!
} else {
// Ball bounces back as before
ball.vy = Math.abs(ball.vy) * 0.5;
ball.vx = ball.vx * 0.5;
ball.isMoving = true;
// After bounce, reset after short delay
LK.setTimeout(function () {
resetBall();
}, 700);
}
}
// Goal
else if (isGoal(ball)) {
shotInProgress = false;
score++;
scoreTxt.setText('Gol: ' + score);
// Play goal sound
LK.getSound('goll').play();
LK.effects.flashScreen(0x00ff00, 400);
// Animate ball into net
tween(ball, {
y: goal.y - 80
}, {
duration: 250,
easing: tween.cubicOut,
onFinish: function onFinish() {
resetBall();
}
});
// Win condition
if (score >= maxGoals) {
endGame(true);
LK.clearInterval(timerInterval);
}
}
// Yan duvarlara çarpınca top seksin, dışarı çıkmasın
else if (ball.x - ball.radius < 0) {
ball.x = ball.radius;
ball.vx = -ball.vx * 0.7; // Damping for realism
// Top köşeden kaleye yönlendirilsin
if (ball.y < goal.y + goal.children[0].height / 2 + 40) {
// Top üst köşede ise, kaleye doğru yönlendir
ball.vy = -Math.abs(ball.vy) * 0.8;
ball.vx = Math.abs(ball.vx) * 0.7;
}
} else if (ball.x + ball.radius > 2048) {
ball.x = 2048 - ball.radius;
ball.vx = -ball.vx * 0.7;
if (ball.y < goal.y + goal.children[0].height / 2 + 40) {
ball.vy = -Math.abs(ball.vy) * 0.8;
ball.vx = -Math.abs(ball.vx) * 0.7;
}
// Ball never leaves the field now; no reset needed for out-of-bounds
}
// If the shot is in progress, the ball is not moving anymore, and it's not a goal or save, play ungol sound
if (shotInProgress && !ball.isMoving) {
// Not a goal, not a save, and the ball stopped: missed shot
LK.getSound('ungol').play();
shotInProgress = false;
// Optionally, reset the ball after a short delay for user feedback
LK.setTimeout(function () {
resetBall();
}, 700);
}
}
};
// --- Playfield layout notes ---
// Goal: y = 200
// Goalkeeper: y = 310
// Ball: y = 2000 (start)
// All elements centered horizontally
// --- Music, sound, etc. are omitted as per guidelines ---