/**** * 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.gravity = 0.2; self.moving = false; self.update = function () { if (self.moving) { self.x += self.velocityX; self.y += self.velocityY; // Apply gravity for side view self.velocityY += self.gravity; // Apply air resistance self.velocityX *= 0.998; self.velocityY *= 0.999; // Field boundaries if (self.x <= 50) { self.x = 50; self.velocityX *= -0.7; } if (self.x >= screenWidth - 50) { self.x = screenWidth - 50; self.velocityX *= -0.7; } if (self.y <= 50) { self.y = 50; self.velocityY *= -0.7; } if (self.y >= screenHeight - 50) { self.y = screenHeight - 50; self.velocityY *= -0.7; } if (Math.abs(self.velocityX) < 0.3 && Math.abs(self.velocityY) < 0.3) { self.moving = false; self.velocityX = 0; self.velocityY = 0; tween.stop(ballGraphics, { rotation: true }); } } }; self.shoot = function (targetX, targetY, power) { var distance = Math.sqrt((targetX - self.x) * (targetX - self.x) + (targetY - self.y) * (targetY - self.y)); self.velocityX = (targetX - self.x) / distance * power; self.velocityY = (targetY - self.y) / distance * power; self.moving = true; // Add realistic ball spin during movement var spinSpeed = power * 0.3; tween(ballGraphics, { rotation: ballGraphics.rotation + spinSpeed }, { duration: 2000, easing: tween.linear }); // Add ball scale effect for power visualization tween(ballGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(ballGraphics, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200, easing: tween.easeInOut }); } }); LK.getSound('kick').play(); }; return self; }); var Goalkeeper = Container.expand(function () { var self = Container.call(this); var keeperGraphics = self.attachAsset('goalkeeper', { anchorX: 0.5, anchorY: 1.0 }); self.speed = 1.0 + LK.getScore() * 0.3; self.direction = 1; self.directionX = Math.random() > 0.5 ? 1 : -1; self.reactionTime = 0; self.isDiving = false; self.maxReactionTime = 30 - LK.getScore() * 2; if (self.maxReactionTime < 10) { self.maxReactionTime = 10; } // Add realistic goalkeeper breathing animation tween(keeperGraphics, { scaleY: 1.1 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(keeperGraphics, { scaleY: 1.0 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { // Repeat breathing animation LK.setTimeout(function () { if (!self.isDiving) { tween(keeperGraphics, { scaleY: 1.1 }, { duration: 1000, easing: tween.easeInOut }); } }, 500); } }); } }); self.update = function () { // Track ball when it's shot - move towards ball position if (ball.moving) { var ballDistance = Math.sqrt((ball.x - self.x) * (ball.x - self.x) + (ball.y - self.y) * (ball.y - self.y)); var trackingSpeed = self.speed * 0.8; // Move towards ball position when ball is moving if (ballDistance > 30 && !self.isDiving) { var directionToBallX = (ball.x - self.x) / ballDistance; var directionToBallY = (ball.y - self.y) / ballDistance; // Apply tracking movement self.x += directionToBallX * trackingSpeed; self.y += directionToBallY * trackingSpeed; } } else { // Random movement when ball is not moving - both vertical and horizontal if (!self.isDiving && Math.random() < 0.02) { self.direction *= -1; } if (!self.isDiving && Math.random() < 0.015) { self.directionX *= -1; } if (!self.isDiving) { self.y += self.direction * self.speed; // Add horizontal movement self.x += self.directionX * (self.speed * 0.5); } } // Keep within goal bounds (vertical movement for side view) if (self.y <= goalY + 50) { self.y = goalY + 50; self.direction = 1; } if (self.y >= goalY + goalHeight - 50) { self.y = goalY + goalHeight - 50; self.direction = -1; } // Keep within horizontal bounds if (self.x <= goalX - 120) { self.x = goalX - 120; self.directionX = 1; } if (self.x >= goalX - 20) { self.x = goalX - 20; self.directionX = -1; } // React to ball when it's moving toward goal if (ball.moving && ball.x > goalX - 200) { self.reactionTime++; if (self.reactionTime > self.maxReactionTime && !self.isDiving) { self.isDiving = true; var targetY = ball.y; var targetX = Math.max(goalX - 100, Math.min(goalX - 30, ball.x)); // Dive animation with tween - now includes horizontal movement tween(self, { y: targetY, x: targetX, rotation: self.y < targetY ? 0.5 : -0.5 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { // Reset after dive LK.setTimeout(function () { self.isDiving = false; tween(self, { rotation: 0 }, { duration: 300, easing: tween.easeInOut }); }, 1000); } }); } } else { self.reactionTime = 0; } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 1.0 }); self.isKicking = false; // Idle breathing animation self.startIdleAnimation = function () { if (!self.isKicking) { tween(playerGraphics, { scaleY: 1.05 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(playerGraphics, { scaleY: 1.0 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { LK.setTimeout(function () { self.startIdleAnimation(); }, 200); } }); } }); } }; // Kicking animation self.performKick = function () { if (self.isKicking) return; self.isKicking = true; // Stop any idle animations tween.stop(playerGraphics); // Lean back preparation tween(playerGraphics, { rotation: -0.2, scaleX: 0.9 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { // Forward kick motion tween(playerGraphics, { rotation: 0.3, scaleX: 1.2, x: self.x + 30 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { // Return to normal position tween(playerGraphics, { rotation: 0, scaleX: 1.0, x: self.x - 30 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { self.isKicking = false; // Resume idle animation LK.setTimeout(function () { self.startIdleAnimation(); }, 500); } }); } }); } }); }; // Start idle animation initially LK.setTimeout(function () { self.startIdleAnimation(); }, 100); return self; }); var Spectator = Container.expand(function () { var self = Container.call(this); var spectatorGraphics = self.attachAsset('spectator', { anchorX: 0.5, anchorY: 1.0 }); var headGraphics = self.attachAsset('spectatorHead', { anchorX: 0.5, anchorY: 0.5 }); headGraphics.y = -50; self.addChild(headGraphics); self.animationDelay = Math.random() * 2000; self.isCheering = false; // Random spectator colors var colors = [0x4169E1, 0xFF6347, 0x32CD32, 0xFFD700, 0xFF69B4, 0x8A2BE2]; spectatorGraphics.tint = colors[Math.floor(Math.random() * colors.length)]; self.update = function () { // Random cheering animation if (Math.random() < 0.005 && !self.isCheering) { self.isCheering = true; tween(self, { scaleY: 1.2, y: self.y - 20 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { scaleY: 1.0, y: self.y + 20 }, { duration: 300, easing: tween.easeIn, onFinish: function onFinish() { self.isCheering = false; } }); } }); } }; self.celebrateGoal = function () { self.isCheering = true; tween(self, { scaleX: 1.3, scaleY: 1.3, y: self.y - 30 }, { duration: 200, easing: tween.bounceOut, onFinish: function onFinish() { tween(self, { scaleX: 1.0, scaleY: 1.0, y: self.y + 30 }, { duration: 400, easing: tween.easeIn, onFinish: function onFinish() { self.isCheering = false; } }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Game dimensions and positions for side view (90 degrees rotated) var screenWidth = 2048; var screenHeight = 2732; var fieldX = 0; // Position field from left edge for full visibility var goalWidth = 80; // Thinner goal for side view var goalHeight = 1000; // Taller goal for side view var goalX = screenWidth - 200; // Goal positioned relative to centered field var goalY = (screenHeight - goalHeight) / 2; // Center goal vertically var ballStartX = 300; // Ball starts positioned for centered field var ballStartY = screenHeight / 2; // Game state var isAiming = false; var aimStartX = 0; var aimStartY = 0; var gameState = 'waiting'; // 'waiting', 'ready', 'aiming', 'shooting', 'reset' var gameStarted = false; // Create field var field = game.addChild(LK.getAsset('field', { anchorX: 0.5, anchorY: 0.5, x: screenWidth / 2, y: screenHeight / 2, width: screenWidth, // Full screen width height: screenHeight, // Full screen height rotation: Math.PI / 2 // Rotate 90 degrees })); // Create goal var goal = game.addChild(LK.getAsset('goal', { anchorX: 0, anchorY: 0, x: goalX, y: goalY, width: goalWidth, height: goalHeight })); // Create goal posts (visual) for side view var topPost = game.addChild(LK.getAsset('aimLine', { anchorX: 0, anchorY: 0.5, x: goalX, y: goalY, width: goalWidth, height: 12, color: 0xffffff })); var bottomPost = game.addChild(LK.getAsset('aimLine', { anchorX: 0, anchorY: 0.5, x: goalX, y: goalY + goalHeight, width: goalWidth, height: 12, color: 0xffffff })); var goalLine = game.addChild(LK.getAsset('aimLine', { anchorX: 0.5, anchorY: 0, x: goalX, y: goalY, width: 12, height: goalHeight, color: 0xffffff })); // Create ball var ball = game.addChild(new Ball()); ball.x = ballStartX; ball.y = ballStartY; // Create player var player = game.addChild(new Player()); player.x = ballStartX - 80; player.y = ballStartY + 50; // Create goalkeeper var goalkeeper = game.addChild(new Goalkeeper()); goalkeeper.x = goalX - 50; // Position in front of goal goalkeeper.y = goalY + goalHeight / 2; // Create spectators crowd var spectators = []; // Left side spectators (behind ball starting position) for (var i = 0; i < 15; i++) { var spec = new Spectator(); spec.x = 100 + Math.random() * 150; spec.y = 200 + i * 150 + Math.random() * 50; spectators.push(spec); game.addChild(spec); } // Right side spectators (behind goal) for (var j = 0; j < 12; j++) { var spec2 = new Spectator(); spec2.x = screenWidth - 150 + Math.random() * 100; spec2.y = 300 + j * 180 + Math.random() * 60; spectators.push(spec2); game.addChild(spec2); } // Top spectators for (var k = 0; k < 8; k++) { var spec3 = new Spectator(); spec3.x = 400 + k * 200 + Math.random() * 100; spec3.y = 150 + Math.random() * 50; spectators.push(spec3); game.addChild(spec3); } // Bottom spectators for (var l = 0; l < 8; l++) { var spec4 = new Spectator(); spec4.x = 400 + l * 200 + Math.random() * 100; spec4.y = screenHeight - 150 + Math.random() * 50; spectators.push(spec4); game.addChild(spec4); } // Create start button var startButton = game.addChild(LK.getAsset('startButton', { anchorX: 0.5, anchorY: 0.5, x: screenWidth / 2, y: screenHeight / 2 })); var startButtonText = new Text2('START GAME', { size: 50, fill: 0xFFFFFF }); startButtonText.anchor.set(0.5, 0.5); startButtonText.x = screenWidth / 2; startButtonText.y = screenHeight / 2; game.addChild(startButtonText); // Hide game elements initially field.alpha = 0.3; goal.alpha = 0.3; topPost.alpha = 0.3; bottomPost.alpha = 0.3; goalLine.alpha = 0.3; ball.alpha = 0.3; goalkeeper.alpha = 0.3; player.alpha = 0.3; for (var s = 0; s < spectators.length; s++) { spectators[s].alpha = 0.3; } // Create aim line (initially hidden) var aimLine = game.addChild(LK.getAsset('aimLine', { anchorX: 0, anchorY: 0.5, alpha: 0 })); // Create score display var scoreTxt = new Text2('Score: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create instruction text var instructionTxt = new Text2('Click START GAME to begin!', { size: 60, fill: 0xFFFFFF }); instructionTxt.anchor.set(0.5, 1); instructionTxt.y = -50; LK.gui.bottom.addChild(instructionTxt); // Game event handlers game.down = function (x, y, obj) { if (!gameStarted && gameState === 'waiting') { // Check if clicked on start button var buttonBounds = { left: screenWidth / 2 - 200, right: screenWidth / 2 + 200, top: screenHeight / 2 - 50, bottom: screenHeight / 2 + 50 }; if (x >= buttonBounds.left && x <= buttonBounds.right && y >= buttonBounds.top && y <= buttonBounds.bottom) { // Start the game gameStarted = true; gameState = 'ready'; // Hide start button startButton.alpha = 0; startButtonText.alpha = 0; // Show game elements field.alpha = 1; goal.alpha = 1; topPost.alpha = 1; bottomPost.alpha = 1; goalLine.alpha = 1; ball.alpha = 1; goalkeeper.alpha = 1; player.alpha = 1; for (var t = 0; t < spectators.length; t++) { spectators[t].alpha = 1; } // Update instruction text instructionTxt.setText('Drag to aim, release to shoot!'); } } else if (gameState === 'ready') { gameState = 'aiming'; isAiming = true; aimStartX = x; aimStartY = y; aimLine.alpha = 1; } }; game.move = function (x, y, obj) { if (isAiming && gameState === 'aiming') { var dx = x - ball.x; var dy = y - ball.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { aimLine.x = ball.x; aimLine.y = ball.y; var targetWidth = Math.min(distance, 300); // Smooth aim line width transition tween(aimLine, { width: targetWidth }, { duration: 50, easing: tween.easeOut }); aimLine.rotation = Math.atan2(dy, dx); // Power visualization with color change var power = Math.min(distance / 300, 1); var red = Math.floor(255 * power); var green = Math.floor(255 * (1 - power)); var color = red << 16 | green << 8 | 0; tween(aimLine, { tint: color }, { duration: 100, easing: tween.linear }); } } }; game.up = function (x, y, obj) { if (isAiming && gameState === 'aiming') { isAiming = false; aimLine.alpha = 0; gameState = 'shooting'; var dx = x - ball.x; var dy = y - ball.y; var distance = Math.sqrt(dx * dx + dy * dy); var power = Math.min(distance / 10, 25); ball.shoot(x, y, power); player.performKick(); } }; // Reset function function resetGame() { ball.x = ballStartX; ball.y = ballStartY; ball.moving = false; ball.velocityX = 0; ball.velocityY = 0; gameState = 'ready'; goalkeeper.reactionTime = 0; goalkeeper.speed = 1.0 + LK.getScore() * 0.3; goalkeeper.maxReactionTime = 30 - LK.getScore() * 2; if (goalkeeper.maxReactionTime < 10) { goalkeeper.maxReactionTime = 10; } } // Game update loop game.update = function () { // Check for goal if (ball.moving && ball.x > goalX && ball.y > goalY && ball.y < goalY + goalHeight && ball.lastX !== undefined && ball.lastX <= goalX) { // Check if goalkeeper blocked it if (!ball.intersects(goalkeeper)) { LK.setScore(LK.getScore() + 1); scoreTxt.setText('Score: ' + LK.getScore()); LK.getSound('goal').play(); LK.effects.flashScreen(0x00ff00, 500); // Celebrate goal with ball bounce and goal shake tween(ball, { scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.bounceOut, onFinish: function onFinish() { tween(ball, { scaleX: 1.0, scaleY: 1.0 }, { duration: 200 }); } }); // Goal shake effect tween(goal, { x: goalX + 10 }, { duration: 50, easing: tween.easeInOut, onFinish: function onFinish() { tween(goal, { x: goalX - 10 }, { duration: 50, onFinish: function onFinish() { tween(goal, { x: goalX }, { duration: 50 }); } }); } }); // Score text celebration tween(scoreTxt, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(scoreTxt, { scaleX: 1.0, scaleY: 1.0 }, { duration: 300 }); } }); // Make spectators celebrate goal for (var u = 0; u < spectators.length; u++) { LK.setTimeout(function () { var randomSpec = spectators[Math.floor(Math.random() * spectators.length)]; if (randomSpec && randomSpec.celebrateGoal) { randomSpec.celebrateGoal(); } }, Math.random() * 500); } // Reset immediately for continuous play resetGame(); } } // Check for goalkeeper block if (ball.moving && ball.intersects(goalkeeper)) { LK.getSound('block').play(); LK.effects.flashScreen(0xff0000, 500); LK.showGameOver(); } // Check if ball went off screen or stopped moving for too long if (ball.moving && (ball.x < -100 || ball.x > screenWidth + 100 || ball.y < -100 || ball.y > screenHeight + 100)) { LK.showGameOver(); } // Check if ball stopped moving and didn't score if (!ball.moving && gameState === 'shooting') { if (!(ball.x > goalX && ball.y > goalY && ball.y < goalY + goalHeight)) { LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } // Track ball position for collision detection ball.lastX = ball.x; ball.lastY = ball.y; };
/****
* 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.gravity = 0.2;
self.moving = false;
self.update = function () {
if (self.moving) {
self.x += self.velocityX;
self.y += self.velocityY;
// Apply gravity for side view
self.velocityY += self.gravity;
// Apply air resistance
self.velocityX *= 0.998;
self.velocityY *= 0.999;
// Field boundaries
if (self.x <= 50) {
self.x = 50;
self.velocityX *= -0.7;
}
if (self.x >= screenWidth - 50) {
self.x = screenWidth - 50;
self.velocityX *= -0.7;
}
if (self.y <= 50) {
self.y = 50;
self.velocityY *= -0.7;
}
if (self.y >= screenHeight - 50) {
self.y = screenHeight - 50;
self.velocityY *= -0.7;
}
if (Math.abs(self.velocityX) < 0.3 && Math.abs(self.velocityY) < 0.3) {
self.moving = false;
self.velocityX = 0;
self.velocityY = 0;
tween.stop(ballGraphics, {
rotation: true
});
}
}
};
self.shoot = function (targetX, targetY, power) {
var distance = Math.sqrt((targetX - self.x) * (targetX - self.x) + (targetY - self.y) * (targetY - self.y));
self.velocityX = (targetX - self.x) / distance * power;
self.velocityY = (targetY - self.y) / distance * power;
self.moving = true;
// Add realistic ball spin during movement
var spinSpeed = power * 0.3;
tween(ballGraphics, {
rotation: ballGraphics.rotation + spinSpeed
}, {
duration: 2000,
easing: tween.linear
});
// Add ball scale effect for power visualization
tween(ballGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(ballGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
LK.getSound('kick').play();
};
return self;
});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = 1.0 + LK.getScore() * 0.3;
self.direction = 1;
self.directionX = Math.random() > 0.5 ? 1 : -1;
self.reactionTime = 0;
self.isDiving = false;
self.maxReactionTime = 30 - LK.getScore() * 2;
if (self.maxReactionTime < 10) {
self.maxReactionTime = 10;
}
// Add realistic goalkeeper breathing animation
tween(keeperGraphics, {
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(keeperGraphics, {
scaleY: 1.0
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Repeat breathing animation
LK.setTimeout(function () {
if (!self.isDiving) {
tween(keeperGraphics, {
scaleY: 1.1
}, {
duration: 1000,
easing: tween.easeInOut
});
}
}, 500);
}
});
}
});
self.update = function () {
// Track ball when it's shot - move towards ball position
if (ball.moving) {
var ballDistance = Math.sqrt((ball.x - self.x) * (ball.x - self.x) + (ball.y - self.y) * (ball.y - self.y));
var trackingSpeed = self.speed * 0.8;
// Move towards ball position when ball is moving
if (ballDistance > 30 && !self.isDiving) {
var directionToBallX = (ball.x - self.x) / ballDistance;
var directionToBallY = (ball.y - self.y) / ballDistance;
// Apply tracking movement
self.x += directionToBallX * trackingSpeed;
self.y += directionToBallY * trackingSpeed;
}
} else {
// Random movement when ball is not moving - both vertical and horizontal
if (!self.isDiving && Math.random() < 0.02) {
self.direction *= -1;
}
if (!self.isDiving && Math.random() < 0.015) {
self.directionX *= -1;
}
if (!self.isDiving) {
self.y += self.direction * self.speed;
// Add horizontal movement
self.x += self.directionX * (self.speed * 0.5);
}
}
// Keep within goal bounds (vertical movement for side view)
if (self.y <= goalY + 50) {
self.y = goalY + 50;
self.direction = 1;
}
if (self.y >= goalY + goalHeight - 50) {
self.y = goalY + goalHeight - 50;
self.direction = -1;
}
// Keep within horizontal bounds
if (self.x <= goalX - 120) {
self.x = goalX - 120;
self.directionX = 1;
}
if (self.x >= goalX - 20) {
self.x = goalX - 20;
self.directionX = -1;
}
// React to ball when it's moving toward goal
if (ball.moving && ball.x > goalX - 200) {
self.reactionTime++;
if (self.reactionTime > self.maxReactionTime && !self.isDiving) {
self.isDiving = true;
var targetY = ball.y;
var targetX = Math.max(goalX - 100, Math.min(goalX - 30, ball.x));
// Dive animation with tween - now includes horizontal movement
tween(self, {
y: targetY,
x: targetX,
rotation: self.y < targetY ? 0.5 : -0.5
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset after dive
LK.setTimeout(function () {
self.isDiving = false;
tween(self, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}, 1000);
}
});
}
} else {
self.reactionTime = 0;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
self.isKicking = false;
// Idle breathing animation
self.startIdleAnimation = function () {
if (!self.isKicking) {
tween(playerGraphics, {
scaleY: 1.05
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(playerGraphics, {
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
LK.setTimeout(function () {
self.startIdleAnimation();
}, 200);
}
});
}
});
}
};
// Kicking animation
self.performKick = function () {
if (self.isKicking) return;
self.isKicking = true;
// Stop any idle animations
tween.stop(playerGraphics);
// Lean back preparation
tween(playerGraphics, {
rotation: -0.2,
scaleX: 0.9
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
// Forward kick motion
tween(playerGraphics, {
rotation: 0.3,
scaleX: 1.2,
x: self.x + 30
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return to normal position
tween(playerGraphics, {
rotation: 0,
scaleX: 1.0,
x: self.x - 30
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isKicking = false;
// Resume idle animation
LK.setTimeout(function () {
self.startIdleAnimation();
}, 500);
}
});
}
});
}
});
};
// Start idle animation initially
LK.setTimeout(function () {
self.startIdleAnimation();
}, 100);
return self;
});
var Spectator = Container.expand(function () {
var self = Container.call(this);
var spectatorGraphics = self.attachAsset('spectator', {
anchorX: 0.5,
anchorY: 1.0
});
var headGraphics = self.attachAsset('spectatorHead', {
anchorX: 0.5,
anchorY: 0.5
});
headGraphics.y = -50;
self.addChild(headGraphics);
self.animationDelay = Math.random() * 2000;
self.isCheering = false;
// Random spectator colors
var colors = [0x4169E1, 0xFF6347, 0x32CD32, 0xFFD700, 0xFF69B4, 0x8A2BE2];
spectatorGraphics.tint = colors[Math.floor(Math.random() * colors.length)];
self.update = function () {
// Random cheering animation
if (Math.random() < 0.005 && !self.isCheering) {
self.isCheering = true;
tween(self, {
scaleY: 1.2,
y: self.y - 20
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleY: 1.0,
y: self.y + 20
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isCheering = false;
}
});
}
});
}
};
self.celebrateGoal = function () {
self.isCheering = true;
tween(self, {
scaleX: 1.3,
scaleY: 1.3,
y: self.y - 30
}, {
duration: 200,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0,
y: self.y + 30
}, {
duration: 400,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isCheering = false;
}
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game dimensions and positions for side view (90 degrees rotated)
var screenWidth = 2048;
var screenHeight = 2732;
var fieldX = 0; // Position field from left edge for full visibility
var goalWidth = 80; // Thinner goal for side view
var goalHeight = 1000; // Taller goal for side view
var goalX = screenWidth - 200; // Goal positioned relative to centered field
var goalY = (screenHeight - goalHeight) / 2; // Center goal vertically
var ballStartX = 300; // Ball starts positioned for centered field
var ballStartY = screenHeight / 2;
// Game state
var isAiming = false;
var aimStartX = 0;
var aimStartY = 0;
var gameState = 'waiting'; // 'waiting', 'ready', 'aiming', 'shooting', 'reset'
var gameStarted = false;
// Create field
var field = game.addChild(LK.getAsset('field', {
anchorX: 0.5,
anchorY: 0.5,
x: screenWidth / 2,
y: screenHeight / 2,
width: screenWidth,
// Full screen width
height: screenHeight,
// Full screen height
rotation: Math.PI / 2 // Rotate 90 degrees
}));
// Create goal
var goal = game.addChild(LK.getAsset('goal', {
anchorX: 0,
anchorY: 0,
x: goalX,
y: goalY,
width: goalWidth,
height: goalHeight
}));
// Create goal posts (visual) for side view
var topPost = game.addChild(LK.getAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
x: goalX,
y: goalY,
width: goalWidth,
height: 12,
color: 0xffffff
}));
var bottomPost = game.addChild(LK.getAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
x: goalX,
y: goalY + goalHeight,
width: goalWidth,
height: 12,
color: 0xffffff
}));
var goalLine = game.addChild(LK.getAsset('aimLine', {
anchorX: 0.5,
anchorY: 0,
x: goalX,
y: goalY,
width: 12,
height: goalHeight,
color: 0xffffff
}));
// Create ball
var ball = game.addChild(new Ball());
ball.x = ballStartX;
ball.y = ballStartY;
// Create player
var player = game.addChild(new Player());
player.x = ballStartX - 80;
player.y = ballStartY + 50;
// Create goalkeeper
var goalkeeper = game.addChild(new Goalkeeper());
goalkeeper.x = goalX - 50; // Position in front of goal
goalkeeper.y = goalY + goalHeight / 2;
// Create spectators crowd
var spectators = [];
// Left side spectators (behind ball starting position)
for (var i = 0; i < 15; i++) {
var spec = new Spectator();
spec.x = 100 + Math.random() * 150;
spec.y = 200 + i * 150 + Math.random() * 50;
spectators.push(spec);
game.addChild(spec);
}
// Right side spectators (behind goal)
for (var j = 0; j < 12; j++) {
var spec2 = new Spectator();
spec2.x = screenWidth - 150 + Math.random() * 100;
spec2.y = 300 + j * 180 + Math.random() * 60;
spectators.push(spec2);
game.addChild(spec2);
}
// Top spectators
for (var k = 0; k < 8; k++) {
var spec3 = new Spectator();
spec3.x = 400 + k * 200 + Math.random() * 100;
spec3.y = 150 + Math.random() * 50;
spectators.push(spec3);
game.addChild(spec3);
}
// Bottom spectators
for (var l = 0; l < 8; l++) {
var spec4 = new Spectator();
spec4.x = 400 + l * 200 + Math.random() * 100;
spec4.y = screenHeight - 150 + Math.random() * 50;
spectators.push(spec4);
game.addChild(spec4);
}
// Create start button
var startButton = game.addChild(LK.getAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
x: screenWidth / 2,
y: screenHeight / 2
}));
var startButtonText = new Text2('START GAME', {
size: 50,
fill: 0xFFFFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = screenWidth / 2;
startButtonText.y = screenHeight / 2;
game.addChild(startButtonText);
// Hide game elements initially
field.alpha = 0.3;
goal.alpha = 0.3;
topPost.alpha = 0.3;
bottomPost.alpha = 0.3;
goalLine.alpha = 0.3;
ball.alpha = 0.3;
goalkeeper.alpha = 0.3;
player.alpha = 0.3;
for (var s = 0; s < spectators.length; s++) {
spectators[s].alpha = 0.3;
}
// Create aim line (initially hidden)
var aimLine = game.addChild(LK.getAsset('aimLine', {
anchorX: 0,
anchorY: 0.5,
alpha: 0
}));
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create instruction text
var instructionTxt = new Text2('Click START GAME to begin!', {
size: 60,
fill: 0xFFFFFF
});
instructionTxt.anchor.set(0.5, 1);
instructionTxt.y = -50;
LK.gui.bottom.addChild(instructionTxt);
// Game event handlers
game.down = function (x, y, obj) {
if (!gameStarted && gameState === 'waiting') {
// Check if clicked on start button
var buttonBounds = {
left: screenWidth / 2 - 200,
right: screenWidth / 2 + 200,
top: screenHeight / 2 - 50,
bottom: screenHeight / 2 + 50
};
if (x >= buttonBounds.left && x <= buttonBounds.right && y >= buttonBounds.top && y <= buttonBounds.bottom) {
// Start the game
gameStarted = true;
gameState = 'ready';
// Hide start button
startButton.alpha = 0;
startButtonText.alpha = 0;
// Show game elements
field.alpha = 1;
goal.alpha = 1;
topPost.alpha = 1;
bottomPost.alpha = 1;
goalLine.alpha = 1;
ball.alpha = 1;
goalkeeper.alpha = 1;
player.alpha = 1;
for (var t = 0; t < spectators.length; t++) {
spectators[t].alpha = 1;
}
// Update instruction text
instructionTxt.setText('Drag to aim, release to shoot!');
}
} else if (gameState === 'ready') {
gameState = 'aiming';
isAiming = true;
aimStartX = x;
aimStartY = y;
aimLine.alpha = 1;
}
};
game.move = function (x, y, obj) {
if (isAiming && gameState === 'aiming') {
var dx = x - ball.x;
var dy = y - ball.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
aimLine.x = ball.x;
aimLine.y = ball.y;
var targetWidth = Math.min(distance, 300);
// Smooth aim line width transition
tween(aimLine, {
width: targetWidth
}, {
duration: 50,
easing: tween.easeOut
});
aimLine.rotation = Math.atan2(dy, dx);
// Power visualization with color change
var power = Math.min(distance / 300, 1);
var red = Math.floor(255 * power);
var green = Math.floor(255 * (1 - power));
var color = red << 16 | green << 8 | 0;
tween(aimLine, {
tint: color
}, {
duration: 100,
easing: tween.linear
});
}
}
};
game.up = function (x, y, obj) {
if (isAiming && gameState === 'aiming') {
isAiming = false;
aimLine.alpha = 0;
gameState = 'shooting';
var dx = x - ball.x;
var dy = y - ball.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var power = Math.min(distance / 10, 25);
ball.shoot(x, y, power);
player.performKick();
}
};
// Reset function
function resetGame() {
ball.x = ballStartX;
ball.y = ballStartY;
ball.moving = false;
ball.velocityX = 0;
ball.velocityY = 0;
gameState = 'ready';
goalkeeper.reactionTime = 0;
goalkeeper.speed = 1.0 + LK.getScore() * 0.3;
goalkeeper.maxReactionTime = 30 - LK.getScore() * 2;
if (goalkeeper.maxReactionTime < 10) {
goalkeeper.maxReactionTime = 10;
}
}
// Game update loop
game.update = function () {
// Check for goal
if (ball.moving && ball.x > goalX && ball.y > goalY && ball.y < goalY + goalHeight && ball.lastX !== undefined && ball.lastX <= goalX) {
// Check if goalkeeper blocked it
if (!ball.intersects(goalkeeper)) {
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('goal').play();
LK.effects.flashScreen(0x00ff00, 500);
// Celebrate goal with ball bounce and goal shake
tween(ball, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(ball, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200
});
}
});
// Goal shake effect
tween(goal, {
x: goalX + 10
}, {
duration: 50,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(goal, {
x: goalX - 10
}, {
duration: 50,
onFinish: function onFinish() {
tween(goal, {
x: goalX
}, {
duration: 50
});
}
});
}
});
// Score text celebration
tween(scoreTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300
});
}
});
// Make spectators celebrate goal
for (var u = 0; u < spectators.length; u++) {
LK.setTimeout(function () {
var randomSpec = spectators[Math.floor(Math.random() * spectators.length)];
if (randomSpec && randomSpec.celebrateGoal) {
randomSpec.celebrateGoal();
}
}, Math.random() * 500);
}
// Reset immediately for continuous play
resetGame();
}
}
// Check for goalkeeper block
if (ball.moving && ball.intersects(goalkeeper)) {
LK.getSound('block').play();
LK.effects.flashScreen(0xff0000, 500);
LK.showGameOver();
}
// Check if ball went off screen or stopped moving for too long
if (ball.moving && (ball.x < -100 || ball.x > screenWidth + 100 || ball.y < -100 || ball.y > screenHeight + 100)) {
LK.showGameOver();
}
// Check if ball stopped moving and didn't score
if (!ball.moving && gameState === 'shooting') {
if (!(ball.x > goalX && ball.y > goalY && ball.y < goalY + goalHeight)) {
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Track ball position for collision detection
ball.lastX = ball.x;
ball.lastY = ball.y;
};