/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Ball = Container.expand(function () { var self = Container.call(this); var ballGraphics = self.attachAsset('ball', { anchorX: 0.5, anchorY: 0.5 }); self.vx = 0; self.vy = 0; self.power = 0; self.angle = 0; self.isMoving = false; self.isScored = false; self.shoot = function (power, angle) { self.power = power; self.angle = angle; self.vx = Math.sin(angle) * power; self.vy = -Math.cos(angle) * power; self.isMoving = true; LK.getSound('kick').play(); }; self.reset = function () { self.x = 1024; self.y = 2200; self.vx = 0; self.vy = 0; self.isMoving = false; self.isScored = false; self.alpha = 1; self.scale.set(1, 1); }; self.update = function () { if (self.isMoving) { // Apply gravity and friction self.vy += 0.2; self.vx *= 0.99; // Update position self.x += self.vx; self.y += self.vy; // Spin effect (visual) self.rotation += self.vx * 0.01; } }; return self; }); var Goal = Container.expand(function () { var self = Container.call(this); // Goal structure var goalNet = self.attachAsset('goalNet', { anchorX: 0.5, anchorY: 0, alpha: 0.3 }); var goalPost = self.attachAsset('goalPost', { anchorX: 0.5, anchorY: 0.5, y: -20 }); // Goal dimensions self.width = 1200; self.height = 400; self.postWidth = 1200; self.postHeight = 20; // Position the goal elements goalNet.y = 0; self.isInGoal = function (ball) { // Check if ball is in goal area var ballCenterX = ball.x; var ballCenterY = ball.y; var ballRadius = ball.width / 2; var goalLeft = self.x - self.width / 2; var goalRight = self.x + self.width / 2; var goalTop = self.y; var goalBottom = self.y + self.height; return ballCenterX + ballRadius > goalLeft && ballCenterX - ballRadius < goalRight && ballCenterY + ballRadius > goalTop && ballCenterY - ballRadius < goalBottom; }; self.hitPost = function (ball) { // Check if ball hit the post var ballCenterX = ball.x; var ballCenterY = ball.y; var ballRadius = ball.width / 2; var postLeft = self.x - self.postWidth / 2; var postRight = self.x + self.postWidth / 2; var postTop = self.y - self.postHeight / 2; var postBottom = self.y + self.postHeight / 2; // Check vertical proximity to post var verticalProximity = Math.abs(ballCenterY - self.y) < ballRadius + self.postHeight / 2; // Check horizontal position near posts var nearLeftPost = Math.abs(ballCenterX - postLeft) < ballRadius * 1.5; var nearRightPost = Math.abs(ballCenterX - postRight) < ballRadius * 1.5; return verticalProximity && (nearLeftPost || nearRightPost); }; return self; }); var Goalkeeper = Container.expand(function () { var self = Container.call(this); var keeperGraphics = self.attachAsset('goalkeeper', { anchorX: 0.5, anchorY: 0.5 }); self.targetX = 0; self.targetY = 0; self.isDiving = false; self.divingDirection = 0; // -1 left, 0 center, 1 right self.aiControlled = true; self.reset = function () { self.x = 1024; self.y = 900; self.isDiving = false; self.divingDirection = 0; tween.stop(self); }; self.dive = function (direction) { if (self.isDiving) { return; } self.isDiving = true; self.divingDirection = direction; var targetX = self.x; var targetY = self.y; // Dive direction (-1 left, 0 center, 1 right) if (direction < -0.33) { // Dive left targetX = 724; targetY = 950; } else if (direction > 0.33) { // Dive right targetX = 1324; targetY = 950; } else { // Stay center or slightly crouch targetY = 950; } tween(self, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut }); }; self.makeAIDecision = function (ballDirection) { if (!self.aiControlled) { return; } // 70% chance of diving in correct direction // 30% chance of diving wrong or staying in center var randomChance = Math.random(); var diveDirection; if (randomChance < 0.7) { // Correct direction with some variation diveDirection = ballDirection + (Math.random() * 0.4 - 0.2); } else { // Wrong direction diveDirection = -ballDirection + (Math.random() * 0.8 - 0.4); } // Clamp dive direction diveDirection = Math.max(-1, Math.min(1, diveDirection)); self.dive(diveDirection); }; return self; }); var ScoreBoard = Container.expand(function () { var self = Container.call(this); self.playerScoreMarkers = []; self.aiScoreMarkers = []; self.playerScore = 0; self.aiScore = 0; self.currentKick = 0; self.maxKicks = 5; var playerLabel = new Text2('Player', { size: 50, fill: 0xFFFFFF }); playerLabel.anchor.set(0, 0.5); playerLabel.x = 0; playerLabel.y = 0; self.addChild(playerLabel); var aiLabel = new Text2('Computer', { size: 50, fill: 0xFFFFFF }); aiLabel.anchor.set(0, 0.5); aiLabel.x = 0; aiLabel.y = 80; self.addChild(aiLabel); // Create score markers for (var i = 0; i < self.maxKicks; i++) { var playerMarker = LK.getAsset('scoreMarker', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); playerMarker.x = 200 + i * 60; playerMarker.y = 0; self.addChild(playerMarker); self.playerScoreMarkers.push(playerMarker); var aiMarker = LK.getAsset('scoreMarker', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); aiMarker.x = 200 + i * 60; aiMarker.y = 80; self.addChild(aiMarker); self.aiScoreMarkers.push(aiMarker); } self.updateScore = function (isPlayer, scored) { if (isPlayer) { if (scored) { self.playerScore++; self.playerScoreMarkers[self.currentKick].tint = 0x03a9f4; self.playerScoreMarkers[self.currentKick].alpha = 1; } else { self.playerScoreMarkers[self.currentKick].tint = 0xff5252; self.playerScoreMarkers[self.currentKick].alpha = 1; } } else { if (scored) { self.aiScore++; self.aiScoreMarkers[self.currentKick].tint = 0x03a9f4; self.aiScoreMarkers[self.currentKick].alpha = 1; } else { self.aiScoreMarkers[self.currentKick].tint = 0xff5252; self.aiScoreMarkers[self.currentKick].alpha = 1; } self.currentKick++; } }; self.reset = function () { self.playerScore = 0; self.aiScore = 0; self.currentKick = 0; for (var i = 0; i < self.maxKicks; i++) { self.playerScoreMarkers[i].tint = 0xffffff; self.playerScoreMarkers[i].alpha = 0.5; self.aiScoreMarkers[i].tint = 0xffffff; self.aiScoreMarkers[i].alpha = 0.5; } }; self.isGameOver = function () { // Check if all kicks have been taken if (self.currentKick >= self.maxKicks) { return true; } // Check if one team has an insurmountable lead var remainingKicks = self.maxKicks - self.currentKick; if (self.playerScore > self.aiScore + remainingKicks) { return true; } if (self.aiScore > self.playerScore + remainingKicks) { return true; } return false; }; return self; }); var StrikerTarget = Container.expand(function () { var self = Container.call(this); var targetGraphics = self.attachAsset('strikerTarget', { anchorX: 0.5, anchorY: 0.5, alpha: 0.6 }); self.show = function () { self.visible = true; self.alpha = 0; tween(self, { alpha: 0.6 }, { duration: 300 }); }; self.hide = function () { tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { self.visible = false; } }); }; self.down = function (x, y, obj) { // Handle touch events for the target }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2e7d32 }); /**** * Game Code ****/ // Game field var field = LK.getAsset('field', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); game.addChild(field); // Game state var gameState = "WAITING"; // WAITING, PLAYER_TURN, AI_TURN, TRANSITION var playerTurn = true; var shootPhase = false; // true for shooting, false for aiming // Goal var goal = new Goal(); goal.x = 1024; goal.y = 800; game.addChild(goal); // Goalkeeper var goalkeeper = new Goalkeeper(); goalkeeper.reset(); game.addChild(goalkeeper); // Ball var ball = new Ball(); ball.reset(); game.addChild(ball); // Target for striker aim var strikerTarget = new StrikerTarget(); strikerTarget.x = 1024; strikerTarget.y = 900; strikerTarget.visible = false; game.addChild(strikerTarget); // Power bar var powerBarBackground = LK.getAsset('goalPost', { anchorX: 0.5, anchorY: 0.5, tint: 0x333333, alpha: 0.5, scaleX: 0.8, scaleY: 1.5 }); powerBarBackground.x = 1024; powerBarBackground.y = 2500; powerBarBackground.visible = false; game.addChild(powerBarBackground); var powerBarFill = LK.getAsset('goalPost', { anchorX: 0, anchorY: 0.5, tint: 0xff9800, scaleY: 1.3 }); powerBarFill.x = powerBarBackground.x - powerBarBackground.width * 0.8 / 2; powerBarFill.y = powerBarBackground.y; powerBarFill.width = 0; powerBarFill.visible = false; game.addChild(powerBarFill); // Game UI var turnIndicator = new Text2('Your Turn: Aim & Shoot', { size: 80, fill: 0xFFFFFF }); turnIndicator.anchor.set(0.5, 0.5); turnIndicator.x = 1024; turnIndicator.y = 200; LK.gui.top.addChild(turnIndicator); var scoreText = new Text2('Player 0 - 0 Computer', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Scoreboard var scoreBoard = new ScoreBoard(); scoreBoard.x = 50; scoreBoard.y = 100; LK.gui.topLeft.addChild(scoreBoard); // Game variables var powerIncreasing = true; var currentPower = 0; var maxPower = 25; var shootAngle = 0; var dragStartX = 0; var dragStartY = 0; // Start game function startGame() { LK.playMusic('bgmusic'); scoreBoard.reset(); startPlayerTurn(); } function startPlayerTurn() { gameState = "PLAYER_TURN"; playerTurn = true; shootPhase = false; ball.reset(); goalkeeper.reset(); goalkeeper.aiControlled = true; strikerTarget.x = 1024; strikerTarget.y = 900; strikerTarget.show(); turnIndicator.setText('Your Turn: Aim & Shoot'); updateScoreDisplay(); } function startAITurn() { gameState = "AI_TURN"; playerTurn = false; shootPhase = false; ball.reset(); goalkeeper.reset(); goalkeeper.aiControlled = false; turnIndicator.setText('Computer\'s Turn'); updateScoreDisplay(); // AI simulates aiming LK.setTimeout(function () { // AI randomly chooses a target var targetX = 724 + Math.random() * 600; var targetY = 700 + Math.random() * 300; // Calculate angle var dx = targetX - ball.x; var dy = targetY - ball.y; var angle = Math.atan2(dx, -dy); // Calculate power var distance = Math.sqrt(dx * dx + dy * dy); var power = Math.min(maxPower, 15 + Math.random() * 5); // Shoot LK.getSound('whistle').play(); ball.shoot(power, angle); // Player decides which way to dive turnIndicator.setText('Dive to Save!'); }, 1500); } function handleGoal() { // Determine if the goal is valid var goalValid = false; if (goal.isInGoal(ball)) { // Check if goalkeeper saved it var ballCenterX = ball.x; var ballCenterY = ball.y; var ballRadius = ball.width / 2; var keeperCenterX = goalkeeper.x; var keeperCenterY = goalkeeper.y; var keeperRadius = goalkeeper.width / 2; var dx = ballCenterX - keeperCenterX; var dy = ballCenterY - keeperCenterY; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < ballRadius + keeperRadius) { // Goalkeeper saved it LK.getSound('save').play(); goalValid = false; } else { // Goal scored LK.getSound('crowd').play(); goalValid = true; ball.isScored = true; // Celebrate tween(ball, { alpha: 0.7 }, { duration: 1000 }); } } else if (goal.hitPost(ball)) { // Hit the post LK.getSound('goalpost').play(); // Bounce effect ball.vx = -ball.vx * 0.5; ball.vy = Math.abs(ball.vy) * 0.7; goalValid = false; } else { // Missed completely goalValid = false; } // Update score scoreBoard.updateScore(playerTurn, goalValid); updateScoreDisplay(); // Transition to next turn LK.setTimeout(function () { if (scoreBoard.isGameOver()) { endGame(); } else { if (playerTurn) { startAITurn(); } else { startPlayerTurn(); } } }, 2000); } function updateScoreDisplay() { scoreText.setText("Player ".concat(scoreBoard.playerScore, " - ").concat(scoreBoard.aiScore, " Computer")); } function endGame() { gameState = "WAITING"; // Determine winner var result = ""; if (scoreBoard.playerScore > scoreBoard.aiScore) { result = "You Win!"; // Check for high score if (scoreBoard.playerScore > storage.highScore) { storage.highScore = scoreBoard.playerScore; } } else if (scoreBoard.playerScore < scoreBoard.aiScore) { result = "Computer Wins!"; } else { result = "It's a Draw!"; } turnIndicator.setText(result); // Show game over LK.setTimeout(function () { LK.showGameOver(); }, 2000); } function updatePowerBar() { if (!shootPhase) { return; } if (powerIncreasing) { currentPower += 0.5; if (currentPower >= maxPower) { currentPower = maxPower; powerIncreasing = false; } } else { currentPower -= 0.5; if (currentPower <= 0) { currentPower = 0; powerIncreasing = true; } } // Update power bar visual var fillWidth = currentPower / maxPower * (powerBarBackground.width * 0.8); powerBarFill.width = fillWidth; // Update color based on power if (currentPower < maxPower * 0.33) { powerBarFill.tint = 0x4caf50; // Green } else if (currentPower < maxPower * 0.66) { powerBarFill.tint = 0xff9800; // Orange } else { powerBarFill.tint = 0xf44336; // Red } } // Game event handlers game.down = function (x, y, obj) { if (gameState !== "PLAYER_TURN") { return; } if (!shootPhase) { // Aiming phase - start drag dragStartX = x; dragStartY = y; // Check if clicked near target var dx = x - strikerTarget.x; var dy = y - strikerTarget.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { strikerTarget.x = x; strikerTarget.y = y; } } else { // Shooting phase - stop power bar powerBarBackground.visible = false; powerBarFill.visible = false; // Calculate angle var dx = strikerTarget.x - ball.x; var dy = strikerTarget.y - ball.y; shootAngle = Math.atan2(dx, -dy); // Goalkeeper AI makes a decision goalkeeper.makeAIDecision(dx > 0 ? 1 : -1); // Shoot the ball ball.shoot(currentPower, shootAngle); // Hide target strikerTarget.hide(); // Update game state shootPhase = false; } }; game.up = function (x, y, obj) { if (gameState !== "PLAYER_TURN" || shootPhase) { return; } // Check if we moved enough to consider it a drag var dx = x - dragStartX; var dy = y - dragStartY; var dragDistance = Math.sqrt(dx * dx + dy * dy); if (dragDistance < 10) { // Not a significant drag - if we clicked the target enter shoot phase dx = x - strikerTarget.x; dy = y - strikerTarget.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Enter shooting phase shootPhase = true; turnIndicator.setText('Tap to Shoot!'); // Show power bar powerBarBackground.visible = true; powerBarFill.visible = true; currentPower = 0; powerIncreasing = true; } } }; game.move = function (x, y, obj) { if (gameState !== "PLAYER_TURN" || shootPhase) { return; } // Check if we're dragging target var dx = x - dragStartX; var dy = y - dragStartY; var dragDistance = Math.sqrt(dx * dx + dy * dy); if (dragDistance > 10) { // Limit target to goal area + some margin var targetX = Math.max(goal.x - goal.width / 2 - 100, Math.min(goal.x + goal.width / 2 + 100, x)); var targetY = Math.max(goal.y - 100, Math.min(goal.y + goal.height + 100, y)); strikerTarget.x = targetX; strikerTarget.y = targetY; // Update drag start for smoother dragging dragStartX = x; dragStartY = y; } }; // Player goalkeeper controls game.move = function (x, y, obj) { if (gameState !== "PLAYER_TURN" || shootPhase) { return; } // Check if we're dragging target var dx = x - dragStartX; var dy = y - dragStartY; var dragDistance = Math.sqrt(dx * dx + dy * dy); if (dragDistance > 10) { // Limit target to goal area + some margin var targetX = Math.max(goal.x - goal.width / 2 - 100, Math.min(goal.x + goal.width / 2 + 100, x)); var targetY = Math.max(goal.y - 100, Math.min(goal.y + goal.height + 100, y)); strikerTarget.x = targetX; strikerTarget.y = targetY; // Update drag start for smoother dragging dragStartX = x; dragStartY = y; } // If it's AI's turn and ball is moving, allow player to control goalkeeper if (gameState === "AI_TURN" && ball.isMoving && !goalkeeper.isDiving) { // Calculate dive direction based on touch position relative to goal center var direction = (x - goal.x) / (goal.width / 2); direction = Math.max(-1, Math.min(1, direction)); goalkeeper.dive(direction); } }; // Game update loop game.update = function () { // Update ball physics ball.update(); // Check for ball stopping if (ball.isMoving && Math.abs(ball.vx) < 0.1 && Math.abs(ball.vy) < 0.1) { ball.isMoving = false; // Process goal or miss if (!ball.isScored) { handleGoal(); } } // Check for ball out of bounds if (ball.isMoving && (ball.y < 0 || ball.y > 2732 || ball.x < 0 || ball.x > 2048)) { ball.isMoving = false; handleGoal(); } // Update power bar in shooting phase if (shootPhase) { updatePowerBar(); } // Start the game if not started if (gameState === "WAITING") { startGame(); } };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,680 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0
+});
+
+/****
+* Classes
+****/
+var Ball = Container.expand(function () {
+ var self = Container.call(this);
+ var ballGraphics = self.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.vx = 0;
+ self.vy = 0;
+ self.power = 0;
+ self.angle = 0;
+ self.isMoving = false;
+ self.isScored = false;
+ self.shoot = function (power, angle) {
+ self.power = power;
+ self.angle = angle;
+ self.vx = Math.sin(angle) * power;
+ self.vy = -Math.cos(angle) * power;
+ self.isMoving = true;
+ LK.getSound('kick').play();
+ };
+ self.reset = function () {
+ self.x = 1024;
+ self.y = 2200;
+ self.vx = 0;
+ self.vy = 0;
+ self.isMoving = false;
+ self.isScored = false;
+ self.alpha = 1;
+ self.scale.set(1, 1);
+ };
+ self.update = function () {
+ if (self.isMoving) {
+ // Apply gravity and friction
+ self.vy += 0.2;
+ self.vx *= 0.99;
+ // Update position
+ self.x += self.vx;
+ self.y += self.vy;
+ // Spin effect (visual)
+ self.rotation += self.vx * 0.01;
+ }
+ };
+ return self;
+});
+var Goal = Container.expand(function () {
+ var self = Container.call(this);
+ // Goal structure
+ var goalNet = self.attachAsset('goalNet', {
+ anchorX: 0.5,
+ anchorY: 0,
+ alpha: 0.3
+ });
+ var goalPost = self.attachAsset('goalPost', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ y: -20
+ });
+ // Goal dimensions
+ self.width = 1200;
+ self.height = 400;
+ self.postWidth = 1200;
+ self.postHeight = 20;
+ // Position the goal elements
+ goalNet.y = 0;
+ self.isInGoal = function (ball) {
+ // Check if ball is in goal area
+ var ballCenterX = ball.x;
+ var ballCenterY = ball.y;
+ var ballRadius = ball.width / 2;
+ var goalLeft = self.x - self.width / 2;
+ var goalRight = self.x + self.width / 2;
+ var goalTop = self.y;
+ var goalBottom = self.y + self.height;
+ return ballCenterX + ballRadius > goalLeft && ballCenterX - ballRadius < goalRight && ballCenterY + ballRadius > goalTop && ballCenterY - ballRadius < goalBottom;
+ };
+ self.hitPost = function (ball) {
+ // Check if ball hit the post
+ var ballCenterX = ball.x;
+ var ballCenterY = ball.y;
+ var ballRadius = ball.width / 2;
+ var postLeft = self.x - self.postWidth / 2;
+ var postRight = self.x + self.postWidth / 2;
+ var postTop = self.y - self.postHeight / 2;
+ var postBottom = self.y + self.postHeight / 2;
+ // Check vertical proximity to post
+ var verticalProximity = Math.abs(ballCenterY - self.y) < ballRadius + self.postHeight / 2;
+ // Check horizontal position near posts
+ var nearLeftPost = Math.abs(ballCenterX - postLeft) < ballRadius * 1.5;
+ var nearRightPost = Math.abs(ballCenterX - postRight) < ballRadius * 1.5;
+ return verticalProximity && (nearLeftPost || nearRightPost);
+ };
+ return self;
+});
+var Goalkeeper = Container.expand(function () {
+ var self = Container.call(this);
+ var keeperGraphics = self.attachAsset('goalkeeper', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.targetX = 0;
+ self.targetY = 0;
+ self.isDiving = false;
+ self.divingDirection = 0; // -1 left, 0 center, 1 right
+ self.aiControlled = true;
+ self.reset = function () {
+ self.x = 1024;
+ self.y = 900;
+ self.isDiving = false;
+ self.divingDirection = 0;
+ tween.stop(self);
+ };
+ self.dive = function (direction) {
+ if (self.isDiving) {
+ return;
+ }
+ self.isDiving = true;
+ self.divingDirection = direction;
+ var targetX = self.x;
+ var targetY = self.y;
+ // Dive direction (-1 left, 0 center, 1 right)
+ if (direction < -0.33) {
+ // Dive left
+ targetX = 724;
+ targetY = 950;
+ } else if (direction > 0.33) {
+ // Dive right
+ targetX = 1324;
+ targetY = 950;
+ } else {
+ // Stay center or slightly crouch
+ targetY = 950;
+ }
+ tween(self, {
+ x: targetX,
+ y: targetY
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ };
+ self.makeAIDecision = function (ballDirection) {
+ if (!self.aiControlled) {
+ return;
+ }
+ // 70% chance of diving in correct direction
+ // 30% chance of diving wrong or staying in center
+ var randomChance = Math.random();
+ var diveDirection;
+ if (randomChance < 0.7) {
+ // Correct direction with some variation
+ diveDirection = ballDirection + (Math.random() * 0.4 - 0.2);
+ } else {
+ // Wrong direction
+ diveDirection = -ballDirection + (Math.random() * 0.8 - 0.4);
+ }
+ // Clamp dive direction
+ diveDirection = Math.max(-1, Math.min(1, diveDirection));
+ self.dive(diveDirection);
+ };
+ return self;
+});
+var ScoreBoard = Container.expand(function () {
+ var self = Container.call(this);
+ self.playerScoreMarkers = [];
+ self.aiScoreMarkers = [];
+ self.playerScore = 0;
+ self.aiScore = 0;
+ self.currentKick = 0;
+ self.maxKicks = 5;
+ var playerLabel = new Text2('Player', {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ playerLabel.anchor.set(0, 0.5);
+ playerLabel.x = 0;
+ playerLabel.y = 0;
+ self.addChild(playerLabel);
+ var aiLabel = new Text2('Computer', {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ aiLabel.anchor.set(0, 0.5);
+ aiLabel.x = 0;
+ aiLabel.y = 80;
+ self.addChild(aiLabel);
+ // Create score markers
+ for (var i = 0; i < self.maxKicks; i++) {
+ var playerMarker = LK.getAsset('scoreMarker', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.5
+ });
+ playerMarker.x = 200 + i * 60;
+ playerMarker.y = 0;
+ self.addChild(playerMarker);
+ self.playerScoreMarkers.push(playerMarker);
+ var aiMarker = LK.getAsset('scoreMarker', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.5
+ });
+ aiMarker.x = 200 + i * 60;
+ aiMarker.y = 80;
+ self.addChild(aiMarker);
+ self.aiScoreMarkers.push(aiMarker);
+ }
+ self.updateScore = function (isPlayer, scored) {
+ if (isPlayer) {
+ if (scored) {
+ self.playerScore++;
+ self.playerScoreMarkers[self.currentKick].tint = 0x03a9f4;
+ self.playerScoreMarkers[self.currentKick].alpha = 1;
+ } else {
+ self.playerScoreMarkers[self.currentKick].tint = 0xff5252;
+ self.playerScoreMarkers[self.currentKick].alpha = 1;
+ }
+ } else {
+ if (scored) {
+ self.aiScore++;
+ self.aiScoreMarkers[self.currentKick].tint = 0x03a9f4;
+ self.aiScoreMarkers[self.currentKick].alpha = 1;
+ } else {
+ self.aiScoreMarkers[self.currentKick].tint = 0xff5252;
+ self.aiScoreMarkers[self.currentKick].alpha = 1;
+ }
+ self.currentKick++;
+ }
+ };
+ self.reset = function () {
+ self.playerScore = 0;
+ self.aiScore = 0;
+ self.currentKick = 0;
+ for (var i = 0; i < self.maxKicks; i++) {
+ self.playerScoreMarkers[i].tint = 0xffffff;
+ self.playerScoreMarkers[i].alpha = 0.5;
+ self.aiScoreMarkers[i].tint = 0xffffff;
+ self.aiScoreMarkers[i].alpha = 0.5;
+ }
+ };
+ self.isGameOver = function () {
+ // Check if all kicks have been taken
+ if (self.currentKick >= self.maxKicks) {
+ return true;
+ }
+ // Check if one team has an insurmountable lead
+ var remainingKicks = self.maxKicks - self.currentKick;
+ if (self.playerScore > self.aiScore + remainingKicks) {
+ return true;
+ }
+ if (self.aiScore > self.playerScore + remainingKicks) {
+ return true;
+ }
+ return false;
+ };
+ return self;
+});
+var StrikerTarget = Container.expand(function () {
+ var self = Container.call(this);
+ var targetGraphics = self.attachAsset('strikerTarget', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.6
+ });
+ self.show = function () {
+ self.visible = true;
+ self.alpha = 0;
+ tween(self, {
+ alpha: 0.6
+ }, {
+ duration: 300
+ });
+ };
+ self.hide = function () {
+ tween(self, {
+ alpha: 0
+ }, {
+ duration: 300,
+ onFinish: function onFinish() {
+ self.visible = false;
+ }
+ });
+ };
+ self.down = function (x, y, obj) {
+ // Handle touch events for the target
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x2e7d32
+});
+
+/****
+* Game Code
+****/
+// Game field
+var field = LK.getAsset('field', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1366
+});
+game.addChild(field);
+// Game state
+var gameState = "WAITING"; // WAITING, PLAYER_TURN, AI_TURN, TRANSITION
+var playerTurn = true;
+var shootPhase = false; // true for shooting, false for aiming
+// Goal
+var goal = new Goal();
+goal.x = 1024;
+goal.y = 800;
+game.addChild(goal);
+// Goalkeeper
+var goalkeeper = new Goalkeeper();
+goalkeeper.reset();
+game.addChild(goalkeeper);
+// Ball
+var ball = new Ball();
+ball.reset();
+game.addChild(ball);
+// Target for striker aim
+var strikerTarget = new StrikerTarget();
+strikerTarget.x = 1024;
+strikerTarget.y = 900;
+strikerTarget.visible = false;
+game.addChild(strikerTarget);
+// Power bar
+var powerBarBackground = LK.getAsset('goalPost', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x333333,
+ alpha: 0.5,
+ scaleX: 0.8,
+ scaleY: 1.5
+});
+powerBarBackground.x = 1024;
+powerBarBackground.y = 2500;
+powerBarBackground.visible = false;
+game.addChild(powerBarBackground);
+var powerBarFill = LK.getAsset('goalPost', {
+ anchorX: 0,
+ anchorY: 0.5,
+ tint: 0xff9800,
+ scaleY: 1.3
+});
+powerBarFill.x = powerBarBackground.x - powerBarBackground.width * 0.8 / 2;
+powerBarFill.y = powerBarBackground.y;
+powerBarFill.width = 0;
+powerBarFill.visible = false;
+game.addChild(powerBarFill);
+// Game UI
+var turnIndicator = new Text2('Your Turn: Aim & Shoot', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+turnIndicator.anchor.set(0.5, 0.5);
+turnIndicator.x = 1024;
+turnIndicator.y = 200;
+LK.gui.top.addChild(turnIndicator);
+var scoreText = new Text2('Player 0 - 0 Computer', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+scoreText.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreText);
+// Scoreboard
+var scoreBoard = new ScoreBoard();
+scoreBoard.x = 50;
+scoreBoard.y = 100;
+LK.gui.topLeft.addChild(scoreBoard);
+// Game variables
+var powerIncreasing = true;
+var currentPower = 0;
+var maxPower = 25;
+var shootAngle = 0;
+var dragStartX = 0;
+var dragStartY = 0;
+// Start game
+function startGame() {
+ LK.playMusic('bgmusic');
+ scoreBoard.reset();
+ startPlayerTurn();
+}
+function startPlayerTurn() {
+ gameState = "PLAYER_TURN";
+ playerTurn = true;
+ shootPhase = false;
+ ball.reset();
+ goalkeeper.reset();
+ goalkeeper.aiControlled = true;
+ strikerTarget.x = 1024;
+ strikerTarget.y = 900;
+ strikerTarget.show();
+ turnIndicator.setText('Your Turn: Aim & Shoot');
+ updateScoreDisplay();
+}
+function startAITurn() {
+ gameState = "AI_TURN";
+ playerTurn = false;
+ shootPhase = false;
+ ball.reset();
+ goalkeeper.reset();
+ goalkeeper.aiControlled = false;
+ turnIndicator.setText('Computer\'s Turn');
+ updateScoreDisplay();
+ // AI simulates aiming
+ LK.setTimeout(function () {
+ // AI randomly chooses a target
+ var targetX = 724 + Math.random() * 600;
+ var targetY = 700 + Math.random() * 300;
+ // Calculate angle
+ var dx = targetX - ball.x;
+ var dy = targetY - ball.y;
+ var angle = Math.atan2(dx, -dy);
+ // Calculate power
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ var power = Math.min(maxPower, 15 + Math.random() * 5);
+ // Shoot
+ LK.getSound('whistle').play();
+ ball.shoot(power, angle);
+ // Player decides which way to dive
+ turnIndicator.setText('Dive to Save!');
+ }, 1500);
+}
+function handleGoal() {
+ // Determine if the goal is valid
+ var goalValid = false;
+ if (goal.isInGoal(ball)) {
+ // Check if goalkeeper saved it
+ var ballCenterX = ball.x;
+ var ballCenterY = ball.y;
+ var ballRadius = ball.width / 2;
+ var keeperCenterX = goalkeeper.x;
+ var keeperCenterY = goalkeeper.y;
+ var keeperRadius = goalkeeper.width / 2;
+ var dx = ballCenterX - keeperCenterX;
+ var dy = ballCenterY - keeperCenterY;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < ballRadius + keeperRadius) {
+ // Goalkeeper saved it
+ LK.getSound('save').play();
+ goalValid = false;
+ } else {
+ // Goal scored
+ LK.getSound('crowd').play();
+ goalValid = true;
+ ball.isScored = true;
+ // Celebrate
+ tween(ball, {
+ alpha: 0.7
+ }, {
+ duration: 1000
+ });
+ }
+ } else if (goal.hitPost(ball)) {
+ // Hit the post
+ LK.getSound('goalpost').play();
+ // Bounce effect
+ ball.vx = -ball.vx * 0.5;
+ ball.vy = Math.abs(ball.vy) * 0.7;
+ goalValid = false;
+ } else {
+ // Missed completely
+ goalValid = false;
+ }
+ // Update score
+ scoreBoard.updateScore(playerTurn, goalValid);
+ updateScoreDisplay();
+ // Transition to next turn
+ LK.setTimeout(function () {
+ if (scoreBoard.isGameOver()) {
+ endGame();
+ } else {
+ if (playerTurn) {
+ startAITurn();
+ } else {
+ startPlayerTurn();
+ }
+ }
+ }, 2000);
+}
+function updateScoreDisplay() {
+ scoreText.setText("Player ".concat(scoreBoard.playerScore, " - ").concat(scoreBoard.aiScore, " Computer"));
+}
+function endGame() {
+ gameState = "WAITING";
+ // Determine winner
+ var result = "";
+ if (scoreBoard.playerScore > scoreBoard.aiScore) {
+ result = "You Win!";
+ // Check for high score
+ if (scoreBoard.playerScore > storage.highScore) {
+ storage.highScore = scoreBoard.playerScore;
+ }
+ } else if (scoreBoard.playerScore < scoreBoard.aiScore) {
+ result = "Computer Wins!";
+ } else {
+ result = "It's a Draw!";
+ }
+ turnIndicator.setText(result);
+ // Show game over
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 2000);
+}
+function updatePowerBar() {
+ if (!shootPhase) {
+ return;
+ }
+ if (powerIncreasing) {
+ currentPower += 0.5;
+ if (currentPower >= maxPower) {
+ currentPower = maxPower;
+ powerIncreasing = false;
+ }
+ } else {
+ currentPower -= 0.5;
+ if (currentPower <= 0) {
+ currentPower = 0;
+ powerIncreasing = true;
+ }
+ }
+ // Update power bar visual
+ var fillWidth = currentPower / maxPower * (powerBarBackground.width * 0.8);
+ powerBarFill.width = fillWidth;
+ // Update color based on power
+ if (currentPower < maxPower * 0.33) {
+ powerBarFill.tint = 0x4caf50; // Green
+ } else if (currentPower < maxPower * 0.66) {
+ powerBarFill.tint = 0xff9800; // Orange
+ } else {
+ powerBarFill.tint = 0xf44336; // Red
+ }
+}
+// Game event handlers
+game.down = function (x, y, obj) {
+ if (gameState !== "PLAYER_TURN") {
+ return;
+ }
+ if (!shootPhase) {
+ // Aiming phase - start drag
+ dragStartX = x;
+ dragStartY = y;
+ // Check if clicked near target
+ var dx = x - strikerTarget.x;
+ var dy = y - strikerTarget.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 150) {
+ strikerTarget.x = x;
+ strikerTarget.y = y;
+ }
+ } else {
+ // Shooting phase - stop power bar
+ powerBarBackground.visible = false;
+ powerBarFill.visible = false;
+ // Calculate angle
+ var dx = strikerTarget.x - ball.x;
+ var dy = strikerTarget.y - ball.y;
+ shootAngle = Math.atan2(dx, -dy);
+ // Goalkeeper AI makes a decision
+ goalkeeper.makeAIDecision(dx > 0 ? 1 : -1);
+ // Shoot the ball
+ ball.shoot(currentPower, shootAngle);
+ // Hide target
+ strikerTarget.hide();
+ // Update game state
+ shootPhase = false;
+ }
+};
+game.up = function (x, y, obj) {
+ if (gameState !== "PLAYER_TURN" || shootPhase) {
+ return;
+ }
+ // Check if we moved enough to consider it a drag
+ var dx = x - dragStartX;
+ var dy = y - dragStartY;
+ var dragDistance = Math.sqrt(dx * dx + dy * dy);
+ if (dragDistance < 10) {
+ // Not a significant drag - if we clicked the target enter shoot phase
+ dx = x - strikerTarget.x;
+ dy = y - strikerTarget.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 150) {
+ // Enter shooting phase
+ shootPhase = true;
+ turnIndicator.setText('Tap to Shoot!');
+ // Show power bar
+ powerBarBackground.visible = true;
+ powerBarFill.visible = true;
+ currentPower = 0;
+ powerIncreasing = true;
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ if (gameState !== "PLAYER_TURN" || shootPhase) {
+ return;
+ }
+ // Check if we're dragging target
+ var dx = x - dragStartX;
+ var dy = y - dragStartY;
+ var dragDistance = Math.sqrt(dx * dx + dy * dy);
+ if (dragDistance > 10) {
+ // Limit target to goal area + some margin
+ var targetX = Math.max(goal.x - goal.width / 2 - 100, Math.min(goal.x + goal.width / 2 + 100, x));
+ var targetY = Math.max(goal.y - 100, Math.min(goal.y + goal.height + 100, y));
+ strikerTarget.x = targetX;
+ strikerTarget.y = targetY;
+ // Update drag start for smoother dragging
+ dragStartX = x;
+ dragStartY = y;
+ }
+};
+// Player goalkeeper controls
+game.move = function (x, y, obj) {
+ if (gameState !== "PLAYER_TURN" || shootPhase) {
+ return;
+ }
+ // Check if we're dragging target
+ var dx = x - dragStartX;
+ var dy = y - dragStartY;
+ var dragDistance = Math.sqrt(dx * dx + dy * dy);
+ if (dragDistance > 10) {
+ // Limit target to goal area + some margin
+ var targetX = Math.max(goal.x - goal.width / 2 - 100, Math.min(goal.x + goal.width / 2 + 100, x));
+ var targetY = Math.max(goal.y - 100, Math.min(goal.y + goal.height + 100, y));
+ strikerTarget.x = targetX;
+ strikerTarget.y = targetY;
+ // Update drag start for smoother dragging
+ dragStartX = x;
+ dragStartY = y;
+ }
+ // If it's AI's turn and ball is moving, allow player to control goalkeeper
+ if (gameState === "AI_TURN" && ball.isMoving && !goalkeeper.isDiving) {
+ // Calculate dive direction based on touch position relative to goal center
+ var direction = (x - goal.x) / (goal.width / 2);
+ direction = Math.max(-1, Math.min(1, direction));
+ goalkeeper.dive(direction);
+ }
+};
+// Game update loop
+game.update = function () {
+ // Update ball physics
+ ball.update();
+ // Check for ball stopping
+ if (ball.isMoving && Math.abs(ball.vx) < 0.1 && Math.abs(ball.vy) < 0.1) {
+ ball.isMoving = false;
+ // Process goal or miss
+ if (!ball.isScored) {
+ handleGoal();
+ }
+ }
+ // Check for ball out of bounds
+ if (ball.isMoving && (ball.y < 0 || ball.y > 2732 || ball.x < 0 || ball.x > 2048)) {
+ ball.isMoving = false;
+ handleGoal();
+ }
+ // Update power bar in shooting phase
+ if (shootPhase) {
+ updatePowerBar();
+ }
+ // Start the game if not started
+ if (gameState === "WAITING") {
+ startGame();
+ }
+};
\ No newline at end of file