/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = 0; self.velocityY = 0; self.isMoving = false; self.gravity = 0.3; self.friction = 0.98; self.shoot = function (targetX, targetY, power) { var deltaX = targetX - self.x; var deltaY = targetY - self.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); self.velocityX = deltaX / distance * power * 0.8; self.velocityY = deltaY / distance * power * 0.8; self.isMoving = true; LK.getSound('kick').play(); }; self.update = function () { if (self.isMoving) { self.x += self.velocityX; self.y += self.velocityY; self.velocityX *= self.friction; self.velocityY *= self.friction; // Check collision with players if (typeof players !== 'undefined') { for (var p = 0; p < players.length; p++) { if (self.intersects(players[p])) { // Bounce off player self.velocityX *= -0.5; self.velocityY *= -0.5; // Move ball away from player to prevent sticking var dx = self.x - players[p].x; var dy = self.y - players[p].y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.x = players[p].x + dx / dist * 60; self.y = players[p].y + dy / dist * 60; } break; } } } // Stop ball if moving too slowly if (Math.abs(self.velocityX) < 0.5 && Math.abs(self.velocityY) < 0.5) { self.velocityX = 0; self.velocityY = 0; self.isMoving = false; } } }; return self; }); var Goalkeeper = Container.expand(function () { var self = Container.call(this); var keeperGraphics = self.attachAsset('goalkeeper', { anchorX: 0.5, anchorY: 1 }); self.direction = 1; self.speed = 2; self.minX = 0; self.maxX = 0; self.setMovementRange = function (minX, maxX) { self.minX = minX; self.maxX = maxX; }; self.update = function () { self.x += self.speed * self.direction; if (self.x <= self.minX || self.x >= self.maxX) { self.direction *= -1; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 1 }); self.originalX = 0; self.originalY = 0; self.speed = 1.5; self.maxChaseDistance = 200; self.setOriginalPosition = function (x, y) { self.originalX = x; self.originalY = y; }; self.update = function () { // Only chase ball if it's moving and game is in shooting state if (typeof ball !== 'undefined' && ball.isMoving && gameState === 'shooting') { var deltaX = ball.x - self.x; var deltaY = ball.y - self.y; var distanceToBall = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // Check if ball is within chase range var distanceFromOriginal = Math.sqrt((self.x - self.originalX) * (self.x - self.originalX) + (self.y - self.originalY) * (self.y - self.originalY)); if (distanceToBall < 300 && distanceFromOriginal < self.maxChaseDistance) { // Move towards ball if (distanceToBall > 0) { self.x += deltaX / distanceToBall * self.speed; self.y += deltaY / distanceToBall * self.speed; } } else if (distanceFromOriginal > 10) { // Return to original position if too far away var returnDeltaX = self.originalX - self.x; var returnDeltaY = self.originalY - self.y; var returnDistance = Math.sqrt(returnDeltaX * returnDeltaX + returnDeltaY * returnDeltaY); if (returnDistance > 0) { self.x += returnDeltaX / returnDistance * self.speed * 0.5; self.y += returnDeltaY / returnDistance * self.speed * 0.5; } } } else if (typeof ball !== 'undefined' && !ball.isMoving) { // Return to original position when ball is not moving var returnDeltaX = self.originalX - self.x; var returnDeltaY = self.originalY - self.y; var returnDistance = Math.sqrt(returnDeltaX * returnDeltaX + returnDeltaY * returnDeltaY); if (returnDistance > 5) { self.x += returnDeltaX / returnDistance * self.speed * 0.3; self.y += returnDeltaY / returnDistance * self.speed * 0.3; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game state variables var currentLevel = 1; var gameState = 'aiming'; // 'aiming', 'shooting', 'scored', 'missed' var isDragging = false; var dragStartX = 0; var dragStartY = 0; // Create field var field = game.addChild(LK.getAsset('field', { anchorX: 0.5, anchorY: 1, x: 1024, y: 2732 })); // Goal posts var leftPost = game.addChild(LK.getAsset('goalpost', { anchorX: 0.5, anchorY: 1, x: 824, y: 600 })); var rightPost = game.addChild(LK.getAsset('goalpost', { anchorX: 0.5, anchorY: 1, x: 1224, y: 600 })); var crossbar = game.addChild(LK.getAsset('crossbar', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 400 })); // Create ball var ball = game.addChild(new Ball()); ball.x = 1024; ball.y = 2200; // Create goalkeeper var goalkeeper = game.addChild(new Goalkeeper()); goalkeeper.x = 1024; var goalY = 580; goalkeeper.y = goalY; goalkeeper.setMovementRange(850, 1198); // Create 16 players positioned across the field var players = []; var playerPositions = [ // Defense line (4 players) { x: 600, y: 800 }, { x: 900, y: 850 }, { x: 1148, y: 850 }, { x: 1448, y: 800 }, // Midfield line (6 players) { x: 400, y: 1200 }, { x: 700, y: 1300 }, { x: 1000, y: 1250 }, { x: 1348, y: 1250 }, { x: 1648, y: 1300 }, { x: 1900, y: 1200 }, // Forward line (4 players) { x: 600, y: 1700 }, { x: 900, y: 1650 }, { x: 1148, y: 1650 }, { x: 1448, y: 1700 }, // Additional midfield players (2 players) { x: 512, y: 1500 }, { x: 1536, y: 1500 }]; for (var i = 0; i < playerPositions.length; i++) { var player = game.addChild(new Player()); player.x = playerPositions[i].x; player.y = playerPositions[i].y; player.setOriginalPosition(playerPositions[i].x, playerPositions[i].y); players.push(player); } // Aim line (initially hidden) var aimLine = game.addChild(LK.getAsset('aimLine', { anchorX: 0.5, anchorY: 1, alpha: 0 })); // UI Elements var scoreTxt = new Text2('Level: 1', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var instructionTxt = new Text2('Drag to aim, release to shoot!', { size: 60, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionTxt); function resetLevel() { ball.x = 1024; ball.y = 2200; ball.velocityX = 0; ball.velocityY = 0; ball.isMoving = false; gameState = 'aiming'; aimLine.alpha = 0; // Increase goalkeeper speed with level goalkeeper.speed = 2 + (currentLevel - 1) * 0.5; scoreTxt.setText('Level: ' + currentLevel); } function checkGoal() { // Check if ball is in goal area if (ball.x > 824 && ball.x < 1224 && ball.y < 600 && ball.y > 400) { // Check if goalkeeper didn't save it var distanceToKeeper = Math.abs(ball.x - goalkeeper.x); if (distanceToKeeper > 50) { // Goal scored! gameState = 'scored'; LK.getSound('goal').play(); LK.setScore(LK.getScore() + currentLevel * 10); // Flash screen green LK.effects.flashScreen(0x00ff00, 1000); // Advance to next level after delay LK.setTimeout(function () { currentLevel++; resetLevel(); }, 1500); return true; } else { // Goalkeeper saved it gameState = 'missed'; LK.getSound('save').play(); LK.effects.flashScreen(0xff0000, 500); LK.setTimeout(function () { resetLevel(); }, 1000); return true; } } return false; } function checkMiss() { // Ball went off screen or stopped without scoring if (ball.y < 300 || ball.x < 0 || ball.x > 2048 || !ball.isMoving && gameState === 'shooting') { gameState = 'missed'; LK.setTimeout(function () { resetLevel(); }, 1000); return true; } return false; } // Touch/Mouse handlers game.down = function (x, y, obj) { if (gameState === 'aiming' && !ball.isMoving) { isDragging = true; dragStartX = x; dragStartY = y; aimLine.alpha = 0.7; } }; game.move = function (x, y, obj) { if (isDragging && gameState === 'aiming') { var deltaX = x - ball.x; var deltaY = y - ball.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // Update aim line position and rotation aimLine.x = ball.x; aimLine.y = ball.y; aimLine.rotation = Math.atan2(deltaY, deltaX) + Math.PI / 2; // Scale aim line based on power - increased sensitivity var power = Math.min(distance / 1.5, 80); aimLine.scaleY = power / 8; } }; game.up = function (x, y, obj) { if (isDragging && gameState === 'aiming') { isDragging = false; aimLine.alpha = 0; var deltaX = x - ball.x; var deltaY = y - ball.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); var power = Math.min(distance / 1.5, 80); if (power > 3) { ball.shoot(x, y, power); gameState = 'shooting'; } } }; // Main game loop game.update = function () { // Update goalkeeper movement if (gameState !== 'scored') { goalkeeper.update(); } // Update all players for (var p = 0; p < players.length; p++) { players[p].update(); } // Update ball physics ball.update(); // Check for goal or miss if (gameState === 'shooting') { if (!checkGoal()) { checkMiss(); } } // Win condition - reaching level 10 if (currentLevel > 10) { LK.showYouWin(); } }; // Initialize first level resetLevel();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
self.gravity = 0.3;
self.friction = 0.98;
self.shoot = function (targetX, targetY, power) {
var deltaX = targetX - self.x;
var deltaY = targetY - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
self.velocityX = deltaX / distance * power * 0.8;
self.velocityY = deltaY / distance * power * 0.8;
self.isMoving = true;
LK.getSound('kick').play();
};
self.update = function () {
if (self.isMoving) {
self.x += self.velocityX;
self.y += self.velocityY;
self.velocityX *= self.friction;
self.velocityY *= self.friction;
// Check collision with players
if (typeof players !== 'undefined') {
for (var p = 0; p < players.length; p++) {
if (self.intersects(players[p])) {
// Bounce off player
self.velocityX *= -0.5;
self.velocityY *= -0.5;
// Move ball away from player to prevent sticking
var dx = self.x - players[p].x;
var dy = self.y - players[p].y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.x = players[p].x + dx / dist * 60;
self.y = players[p].y + dy / dist * 60;
}
break;
}
}
}
// Stop ball if moving too slowly
if (Math.abs(self.velocityX) < 0.5 && Math.abs(self.velocityY) < 0.5) {
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
}
}
};
return self;
});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 1
});
self.direction = 1;
self.speed = 2;
self.minX = 0;
self.maxX = 0;
self.setMovementRange = function (minX, maxX) {
self.minX = minX;
self.maxX = maxX;
};
self.update = function () {
self.x += self.speed * self.direction;
if (self.x <= self.minX || self.x >= self.maxX) {
self.direction *= -1;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1
});
self.originalX = 0;
self.originalY = 0;
self.speed = 1.5;
self.maxChaseDistance = 200;
self.setOriginalPosition = function (x, y) {
self.originalX = x;
self.originalY = y;
};
self.update = function () {
// Only chase ball if it's moving and game is in shooting state
if (typeof ball !== 'undefined' && ball.isMoving && gameState === 'shooting') {
var deltaX = ball.x - self.x;
var deltaY = ball.y - self.y;
var distanceToBall = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Check if ball is within chase range
var distanceFromOriginal = Math.sqrt((self.x - self.originalX) * (self.x - self.originalX) + (self.y - self.originalY) * (self.y - self.originalY));
if (distanceToBall < 300 && distanceFromOriginal < self.maxChaseDistance) {
// Move towards ball
if (distanceToBall > 0) {
self.x += deltaX / distanceToBall * self.speed;
self.y += deltaY / distanceToBall * self.speed;
}
} else if (distanceFromOriginal > 10) {
// Return to original position if too far away
var returnDeltaX = self.originalX - self.x;
var returnDeltaY = self.originalY - self.y;
var returnDistance = Math.sqrt(returnDeltaX * returnDeltaX + returnDeltaY * returnDeltaY);
if (returnDistance > 0) {
self.x += returnDeltaX / returnDistance * self.speed * 0.5;
self.y += returnDeltaY / returnDistance * self.speed * 0.5;
}
}
} else if (typeof ball !== 'undefined' && !ball.isMoving) {
// Return to original position when ball is not moving
var returnDeltaX = self.originalX - self.x;
var returnDeltaY = self.originalY - self.y;
var returnDistance = Math.sqrt(returnDeltaX * returnDeltaX + returnDeltaY * returnDeltaY);
if (returnDistance > 5) {
self.x += returnDeltaX / returnDistance * self.speed * 0.3;
self.y += returnDeltaY / returnDistance * self.speed * 0.3;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game state variables
var currentLevel = 1;
var gameState = 'aiming'; // 'aiming', 'shooting', 'scored', 'missed'
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
// Create field
var field = game.addChild(LK.getAsset('field', {
anchorX: 0.5,
anchorY: 1,
x: 1024,
y: 2732
}));
// Goal posts
var leftPost = game.addChild(LK.getAsset('goalpost', {
anchorX: 0.5,
anchorY: 1,
x: 824,
y: 600
}));
var rightPost = game.addChild(LK.getAsset('goalpost', {
anchorX: 0.5,
anchorY: 1,
x: 1224,
y: 600
}));
var crossbar = game.addChild(LK.getAsset('crossbar', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 400
}));
// Create ball
var ball = game.addChild(new Ball());
ball.x = 1024;
ball.y = 2200;
// Create goalkeeper
var goalkeeper = game.addChild(new Goalkeeper());
goalkeeper.x = 1024;
var goalY = 580;
goalkeeper.y = goalY;
goalkeeper.setMovementRange(850, 1198);
// Create 16 players positioned across the field
var players = [];
var playerPositions = [
// Defense line (4 players)
{
x: 600,
y: 800
}, {
x: 900,
y: 850
}, {
x: 1148,
y: 850
}, {
x: 1448,
y: 800
},
// Midfield line (6 players)
{
x: 400,
y: 1200
}, {
x: 700,
y: 1300
}, {
x: 1000,
y: 1250
}, {
x: 1348,
y: 1250
}, {
x: 1648,
y: 1300
}, {
x: 1900,
y: 1200
},
// Forward line (4 players)
{
x: 600,
y: 1700
}, {
x: 900,
y: 1650
}, {
x: 1148,
y: 1650
}, {
x: 1448,
y: 1700
},
// Additional midfield players (2 players)
{
x: 512,
y: 1500
}, {
x: 1536,
y: 1500
}];
for (var i = 0; i < playerPositions.length; i++) {
var player = game.addChild(new Player());
player.x = playerPositions[i].x;
player.y = playerPositions[i].y;
player.setOriginalPosition(playerPositions[i].x, playerPositions[i].y);
players.push(player);
}
// Aim line (initially hidden)
var aimLine = game.addChild(LK.getAsset('aimLine', {
anchorX: 0.5,
anchorY: 1,
alpha: 0
}));
// UI Elements
var scoreTxt = new Text2('Level: 1', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionTxt = new Text2('Drag to aim, release to shoot!', {
size: 60,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionTxt);
function resetLevel() {
ball.x = 1024;
ball.y = 2200;
ball.velocityX = 0;
ball.velocityY = 0;
ball.isMoving = false;
gameState = 'aiming';
aimLine.alpha = 0;
// Increase goalkeeper speed with level
goalkeeper.speed = 2 + (currentLevel - 1) * 0.5;
scoreTxt.setText('Level: ' + currentLevel);
}
function checkGoal() {
// Check if ball is in goal area
if (ball.x > 824 && ball.x < 1224 && ball.y < 600 && ball.y > 400) {
// Check if goalkeeper didn't save it
var distanceToKeeper = Math.abs(ball.x - goalkeeper.x);
if (distanceToKeeper > 50) {
// Goal scored!
gameState = 'scored';
LK.getSound('goal').play();
LK.setScore(LK.getScore() + currentLevel * 10);
// Flash screen green
LK.effects.flashScreen(0x00ff00, 1000);
// Advance to next level after delay
LK.setTimeout(function () {
currentLevel++;
resetLevel();
}, 1500);
return true;
} else {
// Goalkeeper saved it
gameState = 'missed';
LK.getSound('save').play();
LK.effects.flashScreen(0xff0000, 500);
LK.setTimeout(function () {
resetLevel();
}, 1000);
return true;
}
}
return false;
}
function checkMiss() {
// Ball went off screen or stopped without scoring
if (ball.y < 300 || ball.x < 0 || ball.x > 2048 || !ball.isMoving && gameState === 'shooting') {
gameState = 'missed';
LK.setTimeout(function () {
resetLevel();
}, 1000);
return true;
}
return false;
}
// Touch/Mouse handlers
game.down = function (x, y, obj) {
if (gameState === 'aiming' && !ball.isMoving) {
isDragging = true;
dragStartX = x;
dragStartY = y;
aimLine.alpha = 0.7;
}
};
game.move = function (x, y, obj) {
if (isDragging && gameState === 'aiming') {
var deltaX = x - ball.x;
var deltaY = y - ball.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Update aim line position and rotation
aimLine.x = ball.x;
aimLine.y = ball.y;
aimLine.rotation = Math.atan2(deltaY, deltaX) + Math.PI / 2;
// Scale aim line based on power - increased sensitivity
var power = Math.min(distance / 1.5, 80);
aimLine.scaleY = power / 8;
}
};
game.up = function (x, y, obj) {
if (isDragging && gameState === 'aiming') {
isDragging = false;
aimLine.alpha = 0;
var deltaX = x - ball.x;
var deltaY = y - ball.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var power = Math.min(distance / 1.5, 80);
if (power > 3) {
ball.shoot(x, y, power);
gameState = 'shooting';
}
}
};
// Main game loop
game.update = function () {
// Update goalkeeper movement
if (gameState !== 'scored') {
goalkeeper.update();
}
// Update all players
for (var p = 0; p < players.length; p++) {
players[p].update();
}
// Update ball physics
ball.update();
// Check for goal or miss
if (gameState === 'shooting') {
if (!checkGoal()) {
checkMiss();
}
}
// Win condition - reaching level 10
if (currentLevel > 10) {
LK.showYouWin();
}
};
// Initialize first level
resetLevel();