/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Ball class var Ball = Container.expand(function () { var self = Container.call(this); // Ball asset var ball = self.attachAsset('football', { anchorX: 0.5, anchorY: 0.5 }); // Ball speed and direction self.vx = 0; self.vy = 0; // For tracking last position for goal line crossing self.lastY = undefined; self.lastIntersecting = false; // Update method called every tick self.update = function () { self.x += self.vx; self.y += self.vy; }; return self; }); // Glove class (the player) var Glove = Container.expand(function () { var self = Container.call(this); // Left glove var leftGlove = self.attachAsset('leftGlove', { anchorX: 0.5, anchorY: 0.5 }); leftGlove.x = -90; leftGlove.y = 0; // Right glove var rightGlove = self.attachAsset('rightGlove', { anchorX: 0.5, anchorY: 0.5 }); rightGlove.x = 90; rightGlove.y = 0; // For collision detection self.leftGlove = leftGlove; self.rightGlove = rightGlove; // For dragging self.down = function (x, y, obj) { // handled in game.down }; self.up = function (x, y, obj) { // handled in game.up }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a5d1a // dark green, football field }); /**** * Game Code ****/ // Topu tuttuğunda çalacak ses LK.playMusic('arkaplan'); // Game constants var GOAL_Y = 2500; // y position of the goal line (bottom of screen) var GOAL_HEIGHT = 60; // thickness of the goal line var GLOVE_Y = 2300; // starting y for gloves var GLOVE_MIN_X = 200; var GLOVE_MAX_X = 2048 - 200; var GLOVE_MIN_Y = 1800; var GLOVE_MAX_Y = 2600; var BALL_MIN_X = 300; var BALL_MAX_X = 2048 - 300; var BALL_START_Y = 200; var BALL_RADIUS = 60; var GLOVE_RADIUS = 100; var MAX_MISSES = 3; // Score and misses var score = 0; var misses = 0; // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Misses text (bottom center) var missesTxt = new Text2('Misses: 0', { size: 80, fill: 0xFF4444 }); missesTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(missesTxt); // Goal line (visual) var goalLine = LK.getAsset('goalLine', { width: 2048, height: GOAL_HEIGHT, color: 0xffffff, shape: 'box', anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: GOAL_Y + GOAL_HEIGHT / 2 }); game.addChild(goalLine); // Castle border (visual, just above the goal line) var castleBorder = LK.getAsset('goalLine', { width: 2048, height: 80, color: 0x7c5e3c, // brownish for castle shape: 'box', anchorX: 0.5, anchorY: 1, x: 2048 / 2, y: GOAL_Y + GOAL_HEIGHT / 2 }); game.addChild(castleBorder); // Glove (player) var glove = new Glove(); glove.x = 2048 / 2; glove.y = GLOVE_Y; game.addChild(glove); // Balls array var balls = []; // Dragging var dragNode = null; var dragOffsetX = 0; var dragOffsetY = 0; // Ball spawn timer var ballInterval = 90; // ticks between balls (start easy) var lastBallTick = 0; // Difficulty progression function updateDifficulty() { // Ball spawn interval decreases as score increases (minimum 20 ticks) if (score < 10) { ballInterval = 90; } else if (score < 20) { ballInterval = 70; } else if (score < 35) { ballInterval = 55; } else if (score < 50) { ballInterval = 40; } else { ballInterval = 25; } // Make balls come even more frequently as score increases further if (score >= 70) { ballInterval = 20; } } // Ball spawner function spawnBall() { var ball = new Ball(); // Random x within goal width var x = BALL_MIN_X + Math.floor(Math.random() * (BALL_MAX_X - BALL_MIN_X)); ball.x = x; ball.y = BALL_START_Y; // Target y is the goal line, target x is random within goal var targetX = BALL_MIN_X + Math.floor(Math.random() * (BALL_MAX_X - BALL_MIN_X)); var targetY = GOAL_Y; // Speed: base + random, increases with score (scales up with score for difficulty) var baseSpeed = 18 + Math.floor(score / 5) * 2; // Increase speed more frequently var speed = baseSpeed + Math.random() * (4 + Math.floor(score / 10)); // Add more randomness as score increases // Calculate direction var dx = targetX - x; var dy = targetY - BALL_START_Y; var dist = Math.sqrt(dx * dx + dy * dy); ball.vx = dx / dist * speed; ball.vy = dy / dist * speed; // Add to game balls.push(ball); game.addChild(ball); } // Collision detection (circle vs circle) function circlesIntersect(x1, y1, r1, x2, y2, r2) { var dx = x1 - x2; var dy = y1 - y2; var distSq = dx * dx + dy * dy; var rSum = r1 + r2; return distSq <= rSum * rSum; } // Move handler (drag gloves) function handleMove(x, y, obj) { if (dragNode) { // Clamp to allowed area var nx = Math.max(GLOVE_MIN_X, Math.min(GLOVE_MAX_X, x)); var ny = Math.max(GLOVE_MIN_Y, Math.min(GLOVE_MAX_Y, y)); dragNode.x = nx; dragNode.y = ny; } } // Touch/mouse down game.down = function (x, y, obj) { // Only start drag if touch is on gloves (within glove area) var dx = x - glove.x; var dy = y - glove.y; if (dx * dx + dy * dy < GLOVE_RADIUS * GLOVE_RADIUS * 1.5) { dragNode = glove; handleMove(x, y, obj); } }; // Touch/mouse up game.up = function (x, y, obj) { dragNode = null; }; // Touch/mouse move game.move = handleMove; // Main game update game.update = function () { // Spawn balls if (LK.ticks - lastBallTick > ballInterval) { spawnBall(); lastBallTick = LK.ticks; } // Update balls for (var i = balls.length - 1; i >= 0; i--) { var ball = balls[i]; ball.update(); // Save lastY for goal line crossing if (ball.lastY === undefined) { ball.lastY = ball.y; } // Check for save (collision with gloves) var saved = false; // Left glove if (circlesIntersect(ball.x, ball.y, BALL_RADIUS, glove.x + glove.leftGlove.x, glove.y + glove.leftGlove.y, GLOVE_RADIUS)) { saved = true; } // Right glove if (circlesIntersect(ball.x, ball.y, BALL_RADIUS, glove.x + glove.rightGlove.x, glove.y + glove.rightGlove.y, GLOVE_RADIUS)) { saved = true; } if (!ball.lastIntersecting && saved) { // Save! score += 1; scoreTxt.setText(score); updateDifficulty(); // Flash gloves green LK.effects.flashObject(glove, 0x00ff00, 300); // Play save sound LK.getSound('save').play(); // Remove ball ball.destroy(); balls.splice(i, 1); continue; } // Check for miss (crosses goal line) if (ball.lastY < GOAL_Y && ball.y >= GOAL_Y) { // Missed! misses += 1; missesTxt.setText('Misses: ' + misses); // Flash screen red LK.effects.flashScreen(0xff0000, 500); // Play goal sound LK.getSound('goal').play(); // Remove ball ball.destroy(); balls.splice(i, 1); // Game over if too many misses if (misses >= MAX_MISSES) { LK.showGameOver(); return; } continue; } // Remove balls that go off screen if (ball.y > 2800) { ball.destroy(); balls.splice(i, 1); continue; } // Update last states ball.lastY = ball.y; ball.lastIntersecting = saved; } }; // Center gloves on start glove.x = 2048 / 2; glove.y = GLOVE_Y; // Playfield is ready!
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Ball class
var Ball = Container.expand(function () {
var self = Container.call(this);
// Ball asset
var ball = self.attachAsset('football', {
anchorX: 0.5,
anchorY: 0.5
});
// Ball speed and direction
self.vx = 0;
self.vy = 0;
// For tracking last position for goal line crossing
self.lastY = undefined;
self.lastIntersecting = false;
// Update method called every tick
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Glove class (the player)
var Glove = Container.expand(function () {
var self = Container.call(this);
// Left glove
var leftGlove = self.attachAsset('leftGlove', {
anchorX: 0.5,
anchorY: 0.5
});
leftGlove.x = -90;
leftGlove.y = 0;
// Right glove
var rightGlove = self.attachAsset('rightGlove', {
anchorX: 0.5,
anchorY: 0.5
});
rightGlove.x = 90;
rightGlove.y = 0;
// For collision detection
self.leftGlove = leftGlove;
self.rightGlove = rightGlove;
// For dragging
self.down = function (x, y, obj) {
// handled in game.down
};
self.up = function (x, y, obj) {
// handled in game.up
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a5d1a // dark green, football field
});
/****
* Game Code
****/
// Topu tuttuğunda çalacak ses
LK.playMusic('arkaplan');
// Game constants
var GOAL_Y = 2500; // y position of the goal line (bottom of screen)
var GOAL_HEIGHT = 60; // thickness of the goal line
var GLOVE_Y = 2300; // starting y for gloves
var GLOVE_MIN_X = 200;
var GLOVE_MAX_X = 2048 - 200;
var GLOVE_MIN_Y = 1800;
var GLOVE_MAX_Y = 2600;
var BALL_MIN_X = 300;
var BALL_MAX_X = 2048 - 300;
var BALL_START_Y = 200;
var BALL_RADIUS = 60;
var GLOVE_RADIUS = 100;
var MAX_MISSES = 3;
// Score and misses
var score = 0;
var misses = 0;
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Misses text (bottom center)
var missesTxt = new Text2('Misses: 0', {
size: 80,
fill: 0xFF4444
});
missesTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(missesTxt);
// Goal line (visual)
var goalLine = LK.getAsset('goalLine', {
width: 2048,
height: GOAL_HEIGHT,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: GOAL_Y + GOAL_HEIGHT / 2
});
game.addChild(goalLine);
// Castle border (visual, just above the goal line)
var castleBorder = LK.getAsset('goalLine', {
width: 2048,
height: 80,
color: 0x7c5e3c,
// brownish for castle
shape: 'box',
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: GOAL_Y + GOAL_HEIGHT / 2
});
game.addChild(castleBorder);
// Glove (player)
var glove = new Glove();
glove.x = 2048 / 2;
glove.y = GLOVE_Y;
game.addChild(glove);
// Balls array
var balls = [];
// Dragging
var dragNode = null;
var dragOffsetX = 0;
var dragOffsetY = 0;
// Ball spawn timer
var ballInterval = 90; // ticks between balls (start easy)
var lastBallTick = 0;
// Difficulty progression
function updateDifficulty() {
// Ball spawn interval decreases as score increases (minimum 20 ticks)
if (score < 10) {
ballInterval = 90;
} else if (score < 20) {
ballInterval = 70;
} else if (score < 35) {
ballInterval = 55;
} else if (score < 50) {
ballInterval = 40;
} else {
ballInterval = 25;
}
// Make balls come even more frequently as score increases further
if (score >= 70) {
ballInterval = 20;
}
}
// Ball spawner
function spawnBall() {
var ball = new Ball();
// Random x within goal width
var x = BALL_MIN_X + Math.floor(Math.random() * (BALL_MAX_X - BALL_MIN_X));
ball.x = x;
ball.y = BALL_START_Y;
// Target y is the goal line, target x is random within goal
var targetX = BALL_MIN_X + Math.floor(Math.random() * (BALL_MAX_X - BALL_MIN_X));
var targetY = GOAL_Y;
// Speed: base + random, increases with score (scales up with score for difficulty)
var baseSpeed = 18 + Math.floor(score / 5) * 2; // Increase speed more frequently
var speed = baseSpeed + Math.random() * (4 + Math.floor(score / 10)); // Add more randomness as score increases
// Calculate direction
var dx = targetX - x;
var dy = targetY - BALL_START_Y;
var dist = Math.sqrt(dx * dx + dy * dy);
ball.vx = dx / dist * speed;
ball.vy = dy / dist * speed;
// Add to game
balls.push(ball);
game.addChild(ball);
}
// Collision detection (circle vs circle)
function circlesIntersect(x1, y1, r1, x2, y2, r2) {
var dx = x1 - x2;
var dy = y1 - y2;
var distSq = dx * dx + dy * dy;
var rSum = r1 + r2;
return distSq <= rSum * rSum;
}
// Move handler (drag gloves)
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to allowed area
var nx = Math.max(GLOVE_MIN_X, Math.min(GLOVE_MAX_X, x));
var ny = Math.max(GLOVE_MIN_Y, Math.min(GLOVE_MAX_Y, y));
dragNode.x = nx;
dragNode.y = ny;
}
}
// Touch/mouse down
game.down = function (x, y, obj) {
// Only start drag if touch is on gloves (within glove area)
var dx = x - glove.x;
var dy = y - glove.y;
if (dx * dx + dy * dy < GLOVE_RADIUS * GLOVE_RADIUS * 1.5) {
dragNode = glove;
handleMove(x, y, obj);
}
};
// Touch/mouse up
game.up = function (x, y, obj) {
dragNode = null;
};
// Touch/mouse move
game.move = handleMove;
// Main game update
game.update = function () {
// Spawn balls
if (LK.ticks - lastBallTick > ballInterval) {
spawnBall();
lastBallTick = LK.ticks;
}
// Update balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
ball.update();
// Save lastY for goal line crossing
if (ball.lastY === undefined) {
ball.lastY = ball.y;
}
// Check for save (collision with gloves)
var saved = false;
// Left glove
if (circlesIntersect(ball.x, ball.y, BALL_RADIUS, glove.x + glove.leftGlove.x, glove.y + glove.leftGlove.y, GLOVE_RADIUS)) {
saved = true;
}
// Right glove
if (circlesIntersect(ball.x, ball.y, BALL_RADIUS, glove.x + glove.rightGlove.x, glove.y + glove.rightGlove.y, GLOVE_RADIUS)) {
saved = true;
}
if (!ball.lastIntersecting && saved) {
// Save!
score += 1;
scoreTxt.setText(score);
updateDifficulty();
// Flash gloves green
LK.effects.flashObject(glove, 0x00ff00, 300);
// Play save sound
LK.getSound('save').play();
// Remove ball
ball.destroy();
balls.splice(i, 1);
continue;
}
// Check for miss (crosses goal line)
if (ball.lastY < GOAL_Y && ball.y >= GOAL_Y) {
// Missed!
misses += 1;
missesTxt.setText('Misses: ' + misses);
// Flash screen red
LK.effects.flashScreen(0xff0000, 500);
// Play goal sound
LK.getSound('goal').play();
// Remove ball
ball.destroy();
balls.splice(i, 1);
// Game over if too many misses
if (misses >= MAX_MISSES) {
LK.showGameOver();
return;
}
continue;
}
// Remove balls that go off screen
if (ball.y > 2800) {
ball.destroy();
balls.splice(i, 1);
continue;
}
// Update last states
ball.lastY = ball.y;
ball.lastIntersecting = saved;
}
};
// Center gloves on start
glove.x = 2048 / 2;
glove.y = GLOVE_Y;
// Playfield is ready!