/**** * 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.startX = 0; self.startY = 0; self.update = function () { if (self.isMoving) { self.x += self.velocityX; self.y += self.velocityY; // Apply some friction self.velocityX *= 0.99; self.velocityY *= 0.99; // Stop if moving too slowly if (Math.abs(self.velocityX) < 0.1 && Math.abs(self.velocityY) < 0.1) { self.stop(); } } }; self.kickTowards = function (targetX, targetY, power) { var deltaX = targetX - self.x; var deltaY = targetY - self.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance > 0) { self.velocityX = deltaX / distance * power; self.velocityY = deltaY / distance * power; self.isMoving = true; } }; self.stop = function () { self.velocityX = 0; self.velocityY = 0; self.isMoving = false; }; self.reset = function () { self.x = self.startX; self.y = self.startY; self.stop(); }; return self; }); var Goal = Container.expand(function () { var self = Container.call(this); // Goal background var goalArea = self.attachAsset('goal', { anchorX: 0.5, anchorY: 1 }); goalArea.alpha = 0.3; goalArea.scaleX = 3; // Make goal three times as wide // Left goal post var leftPost = self.attachAsset('goalPost', { anchorX: 0.5, anchorY: 1 }); leftPost.x = -300; // Move left post even further left // Right goal post var rightPost = self.attachAsset('goalPost', { anchorX: 0.5, anchorY: 1 }); rightPost.x = 300; // Move right post even further right // Crossbar var crossbar = self.attachAsset('crossbar', { anchorX: 0.5, anchorY: 0.5 }); crossbar.y = -300; crossbar.scaleX = 3; // Make crossbar three times as wide self.checkGoal = function (ball) { // Check if ball is within goal area (even larger goal) var ballInGoalX = ball.x > self.x - 300 && ball.x < self.x + 300; var ballInGoalY = ball.y < self.y && ball.y > self.y - 280; return ballInGoalX && ballInGoalY; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.canKick = true; self.kickCooldown = 0; self.update = function () { if (self.kickCooldown > 0) { self.kickCooldown--; } if (self.kickCooldown <= 0) { self.canKick = true; } }; self.kick = function () { if (self.canKick) { self.canKick = false; self.kickCooldown = 30; // 0.5 second cooldown at 60fps LK.getSound('kick').play(); return true; } return false; }; return self; }); var Rival = Container.expand(function () { var self = Container.call(this); var rivalGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); rivalGraphics.tint = 0xff0000; // Make rival red self.speed = 8; self.targetX = 1024; // Default center position self.active = false; self.update = function () { if (self.active) { // When active, rival can still intercept but the base movement is handled by tween // Move slightly towards ball for interception if (ball && ball.isMoving) { var deltaX = ball.x - self.x; if (Math.abs(deltaX) > 5) { self.x += deltaX > 0 ? 2 : -2; // Slower interception movement } } // Keep rival in bounds self.x = Math.max(200, Math.min(1848, self.x)); } }; self.moveToIntercept = function (ballX) { if (self.active) { self.targetX = ballX; } }; self.activate = function () { self.active = true; }; self.deactivate = function () { self.active = false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x228b22 }); /**** * Game Code ****/ // Game variables var player; var ball; var goal; var rival; var scoreTxt; var dragNode = null; var gameState = 'playing'; // 'playing', 'goal', 'miss' var ballHasBeenKicked = false; var lastBallMoving = false; var lastScore = 0; // Create score display scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 100; // Move down from very top // Create game objects player = game.addChild(new Player()); ball = game.addChild(new Ball()); goal = game.addChild(new Goal()); rival = game.addChild(new Rival()); // Position game objects player.x = 1024; // Center horizontally player.y = 2200; // Near bottom ball.x = 1024; // Center horizontally ball.y = 2000; // Above player ball.startX = ball.x; ball.startY = ball.y; goal.x = 1024; // Center horizontally goal.y = 400; // Near top rival.x = 1024; // Center horizontally rival.y = 600; // In front of goal // Start rival side-to-side movement function startRivalMovement() { // Calculate movement speed based on current score (faster every 10 points) var speedMultiplier = Math.max(0.3, 1 - Math.floor(LK.getScore() / 10) * 0.15); var moveDuration = Math.floor(2000 * speedMultiplier); // Move rival to the right tween(rival, { x: 1700 }, { duration: moveDuration, easing: tween.easeInOut, onFinish: function onFinish() { // Move rival to the left tween(rival, { x: 348 }, { duration: moveDuration, easing: tween.easeInOut, onFinish: function onFinish() { // Continue the cycle startRivalMovement(); } }); } }); } // Start the movement cycle startRivalMovement(); // Update score display function updateScore() { scoreTxt.setText(LK.getScore()); } // Handle goal scoring function handleGoal() { if (gameState === 'playing') { gameState = 'goal'; LK.setScore(LK.getScore() + 1); updateScore(); LK.getSound('goal').play(); // Flash effect LK.effects.flashScreen(0x00ff00, 500); // Reset after delay LK.setTimeout(function () { resetBall(); gameState = 'playing'; }, 1000); } } // Handle ball going off screen (miss) function handleMiss() { if (gameState === 'playing') { gameState = 'miss'; // Reset player score when ball goes out of bounds LK.setScore(0); updateScore(); // Reset after short delay LK.setTimeout(function () { resetBall(); gameState = 'playing'; }, 500); } } // Reset ball to starting position function resetBall() { ball.reset(); ballHasBeenKicked = false; lastBallMoving = false; // Reset rival position rival.x = 1024; rival.targetX = 1024; } // Handle player movement and kicking function handleMove(x, y, obj) { if (dragNode === player) { player.x = x; player.y = y; // Keep player in bounds player.x = Math.max(100, Math.min(1948, player.x)); player.y = Math.max(1500, Math.min(2600, player.y)); } } // Touch/mouse handlers game.move = handleMove; // Variables to track drag for player movement var dragStartX = 0; var dragStartY = 0; game.down = function (x, y, obj) { dragNode = player; dragStartX = x; dragStartY = y; handleMove(x, y, obj); }; game.up = function (x, y, obj) { // If ball is near player and not moving, kick it based on collision direction if (dragNode === player) { var distanceToBall = Math.sqrt((player.x - ball.x) * (player.x - ball.x) + (player.y - ball.y) * (player.y - ball.y)); if (distanceToBall < 160 && !ball.isMoving && player.kick()) { var kickPower = 25; // Calculate kick direction based on where player hits the ball var kickDirectionX = ball.x - player.x; var kickDirectionY = ball.y - player.y; var kickDistance = Math.sqrt(kickDirectionX * kickDirectionX + kickDirectionY * kickDirectionY); if (kickDistance > 0) { // Normalize direction and calculate target kickDirectionX = kickDirectionX / kickDistance; kickDirectionY = kickDirectionY / kickDistance; var targetX = ball.x + kickDirectionX * 800; var targetY = ball.y + kickDirectionY * 800; ball.kickTowards(targetX, targetY, kickPower); ballHasBeenKicked = true; } } } dragNode = null; }; // Main game update loop game.update = function () { // Check if we need to activate rival every 10 points var currentScore = LK.getScore(); if (currentScore >= 10 && Math.floor(currentScore / 10) > Math.floor(lastScore / 10)) { rival.activate(); // Stop current tween and restart with new speed tween.stop(rival); startRivalMovement(); } lastScore = currentScore; // Track ball movement state changes var currentBallMoving = ball.isMoving; // If rival is active and ball is moving, make rival try to intercept if (rival.active && ball.isMoving) { rival.moveToIntercept(ball.x); } // Check if rival blocks the ball if (rival.active && ball.isMoving) { var distanceToRival = Math.sqrt((rival.x - ball.x) * (rival.x - ball.x) + (rival.y - ball.y) * (rival.y - ball.y)); if (distanceToRival < 120) { // Ball hits rival - deflect it and reset score ball.velocityX *= -0.3; ball.velocityY *= -0.3; // Reset player score when rival blocks the shot LK.setScore(0); updateScore(); } } // Check for goal if (ball.isMoving && goal.checkGoal(ball)) { handleGoal(); } // Check if ball went off screen (miss) if (ballHasBeenKicked && lastBallMoving && !currentBallMoving) { // Ball stopped moving after being kicked if (!goal.checkGoal(ball)) { handleMiss(); } } // Check if ball went too far off screen if (ball.y < -100 || ball.x < -100 || ball.x > 2148) { if (ballHasBeenKicked) { handleMiss(); } } // Update last ball moving state lastBallMoving = currentBallMoving; }; // Initialize score updateScore();
/****
* 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.startX = 0;
self.startY = 0;
self.update = function () {
if (self.isMoving) {
self.x += self.velocityX;
self.y += self.velocityY;
// Apply some friction
self.velocityX *= 0.99;
self.velocityY *= 0.99;
// Stop if moving too slowly
if (Math.abs(self.velocityX) < 0.1 && Math.abs(self.velocityY) < 0.1) {
self.stop();
}
}
};
self.kickTowards = function (targetX, targetY, power) {
var deltaX = targetX - self.x;
var deltaY = targetY - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
self.velocityX = deltaX / distance * power;
self.velocityY = deltaY / distance * power;
self.isMoving = true;
}
};
self.stop = function () {
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
};
self.reset = function () {
self.x = self.startX;
self.y = self.startY;
self.stop();
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
// Goal background
var goalArea = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 1
});
goalArea.alpha = 0.3;
goalArea.scaleX = 3; // Make goal three times as wide
// Left goal post
var leftPost = self.attachAsset('goalPost', {
anchorX: 0.5,
anchorY: 1
});
leftPost.x = -300; // Move left post even further left
// Right goal post
var rightPost = self.attachAsset('goalPost', {
anchorX: 0.5,
anchorY: 1
});
rightPost.x = 300; // Move right post even further right
// Crossbar
var crossbar = self.attachAsset('crossbar', {
anchorX: 0.5,
anchorY: 0.5
});
crossbar.y = -300;
crossbar.scaleX = 3; // Make crossbar three times as wide
self.checkGoal = function (ball) {
// Check if ball is within goal area (even larger goal)
var ballInGoalX = ball.x > self.x - 300 && ball.x < self.x + 300;
var ballInGoalY = ball.y < self.y && ball.y > self.y - 280;
return ballInGoalX && ballInGoalY;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.canKick = true;
self.kickCooldown = 0;
self.update = function () {
if (self.kickCooldown > 0) {
self.kickCooldown--;
}
if (self.kickCooldown <= 0) {
self.canKick = true;
}
};
self.kick = function () {
if (self.canKick) {
self.canKick = false;
self.kickCooldown = 30; // 0.5 second cooldown at 60fps
LK.getSound('kick').play();
return true;
}
return false;
};
return self;
});
var Rival = Container.expand(function () {
var self = Container.call(this);
var rivalGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
rivalGraphics.tint = 0xff0000; // Make rival red
self.speed = 8;
self.targetX = 1024; // Default center position
self.active = false;
self.update = function () {
if (self.active) {
// When active, rival can still intercept but the base movement is handled by tween
// Move slightly towards ball for interception
if (ball && ball.isMoving) {
var deltaX = ball.x - self.x;
if (Math.abs(deltaX) > 5) {
self.x += deltaX > 0 ? 2 : -2; // Slower interception movement
}
}
// Keep rival in bounds
self.x = Math.max(200, Math.min(1848, self.x));
}
};
self.moveToIntercept = function (ballX) {
if (self.active) {
self.targetX = ballX;
}
};
self.activate = function () {
self.active = true;
};
self.deactivate = function () {
self.active = false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228b22
});
/****
* Game Code
****/
// Game variables
var player;
var ball;
var goal;
var rival;
var scoreTxt;
var dragNode = null;
var gameState = 'playing'; // 'playing', 'goal', 'miss'
var ballHasBeenKicked = false;
var lastBallMoving = false;
var lastScore = 0;
// Create score display
scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 100; // Move down from very top
// Create game objects
player = game.addChild(new Player());
ball = game.addChild(new Ball());
goal = game.addChild(new Goal());
rival = game.addChild(new Rival());
// Position game objects
player.x = 1024; // Center horizontally
player.y = 2200; // Near bottom
ball.x = 1024; // Center horizontally
ball.y = 2000; // Above player
ball.startX = ball.x;
ball.startY = ball.y;
goal.x = 1024; // Center horizontally
goal.y = 400; // Near top
rival.x = 1024; // Center horizontally
rival.y = 600; // In front of goal
// Start rival side-to-side movement
function startRivalMovement() {
// Calculate movement speed based on current score (faster every 10 points)
var speedMultiplier = Math.max(0.3, 1 - Math.floor(LK.getScore() / 10) * 0.15);
var moveDuration = Math.floor(2000 * speedMultiplier);
// Move rival to the right
tween(rival, {
x: 1700
}, {
duration: moveDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Move rival to the left
tween(rival, {
x: 348
}, {
duration: moveDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Continue the cycle
startRivalMovement();
}
});
}
});
}
// Start the movement cycle
startRivalMovement();
// Update score display
function updateScore() {
scoreTxt.setText(LK.getScore());
}
// Handle goal scoring
function handleGoal() {
if (gameState === 'playing') {
gameState = 'goal';
LK.setScore(LK.getScore() + 1);
updateScore();
LK.getSound('goal').play();
// Flash effect
LK.effects.flashScreen(0x00ff00, 500);
// Reset after delay
LK.setTimeout(function () {
resetBall();
gameState = 'playing';
}, 1000);
}
}
// Handle ball going off screen (miss)
function handleMiss() {
if (gameState === 'playing') {
gameState = 'miss';
// Reset player score when ball goes out of bounds
LK.setScore(0);
updateScore();
// Reset after short delay
LK.setTimeout(function () {
resetBall();
gameState = 'playing';
}, 500);
}
}
// Reset ball to starting position
function resetBall() {
ball.reset();
ballHasBeenKicked = false;
lastBallMoving = false;
// Reset rival position
rival.x = 1024;
rival.targetX = 1024;
}
// Handle player movement and kicking
function handleMove(x, y, obj) {
if (dragNode === player) {
player.x = x;
player.y = y;
// Keep player in bounds
player.x = Math.max(100, Math.min(1948, player.x));
player.y = Math.max(1500, Math.min(2600, player.y));
}
}
// Touch/mouse handlers
game.move = handleMove;
// Variables to track drag for player movement
var dragStartX = 0;
var dragStartY = 0;
game.down = function (x, y, obj) {
dragNode = player;
dragStartX = x;
dragStartY = y;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
// If ball is near player and not moving, kick it based on collision direction
if (dragNode === player) {
var distanceToBall = Math.sqrt((player.x - ball.x) * (player.x - ball.x) + (player.y - ball.y) * (player.y - ball.y));
if (distanceToBall < 160 && !ball.isMoving && player.kick()) {
var kickPower = 25;
// Calculate kick direction based on where player hits the ball
var kickDirectionX = ball.x - player.x;
var kickDirectionY = ball.y - player.y;
var kickDistance = Math.sqrt(kickDirectionX * kickDirectionX + kickDirectionY * kickDirectionY);
if (kickDistance > 0) {
// Normalize direction and calculate target
kickDirectionX = kickDirectionX / kickDistance;
kickDirectionY = kickDirectionY / kickDistance;
var targetX = ball.x + kickDirectionX * 800;
var targetY = ball.y + kickDirectionY * 800;
ball.kickTowards(targetX, targetY, kickPower);
ballHasBeenKicked = true;
}
}
}
dragNode = null;
};
// Main game update loop
game.update = function () {
// Check if we need to activate rival every 10 points
var currentScore = LK.getScore();
if (currentScore >= 10 && Math.floor(currentScore / 10) > Math.floor(lastScore / 10)) {
rival.activate();
// Stop current tween and restart with new speed
tween.stop(rival);
startRivalMovement();
}
lastScore = currentScore;
// Track ball movement state changes
var currentBallMoving = ball.isMoving;
// If rival is active and ball is moving, make rival try to intercept
if (rival.active && ball.isMoving) {
rival.moveToIntercept(ball.x);
}
// Check if rival blocks the ball
if (rival.active && ball.isMoving) {
var distanceToRival = Math.sqrt((rival.x - ball.x) * (rival.x - ball.x) + (rival.y - ball.y) * (rival.y - ball.y));
if (distanceToRival < 120) {
// Ball hits rival - deflect it and reset score
ball.velocityX *= -0.3;
ball.velocityY *= -0.3;
// Reset player score when rival blocks the shot
LK.setScore(0);
updateScore();
}
}
// Check for goal
if (ball.isMoving && goal.checkGoal(ball)) {
handleGoal();
}
// Check if ball went off screen (miss)
if (ballHasBeenKicked && lastBallMoving && !currentBallMoving) {
// Ball stopped moving after being kicked
if (!goal.checkGoal(ball)) {
handleMiss();
}
}
// Check if ball went too far off screen
if (ball.y < -100 || ball.x < -100 || ball.x > 2148) {
if (ballHasBeenKicked) {
handleMiss();
}
}
// Update last ball moving state
lastBallMoving = currentBallMoving;
};
// Initialize score
updateScore();