/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
playerScore: 0,
computerScore: 0,
currentRound: 1,
totalRounds: 5,
difficulty: 1
});
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.direction = {
x: 0,
y: 0
};
self.isMoving = false;
self.curveFactor = 0;
self.reset = function () {
self.x = 1024; // Center of field horizontally
self.y = 2200; // Bottom of field where player stands
self.isMoving = false;
self.speed = 0;
self.direction = {
x: 0,
y: 0
};
self.curveFactor = 0;
self.scaleX = 1;
self.scaleY = 1;
};
self.shoot = function (targetX, targetY, power, curve) {
if (self.isMoving) return;
// Calculate direction vector
self.direction.x = targetX - self.x;
self.direction.y = targetY - self.y;
// Normalize direction vector
var length = Math.sqrt(self.direction.x * self.direction.x + self.direction.y * self.direction.y);
self.direction.x /= length;
self.direction.y /= length;
// Set speed based on power (0-100)
self.speed = 5 + power * 15 / 100;
// Set curve factor (-1 to 1)
self.curveFactor = curve;
self.isMoving = true;
// Play kick sound
LK.getSound('kick').play();
};
self.update = function () {
if (!self.isMoving) return;
// Apply curve to direction (simulating curved shot)
if (self.curveFactor !== 0) {
var perpX = -self.direction.y;
var perpY = self.direction.x;
self.direction.x += perpX * self.curveFactor * 0.01;
self.direction.y += perpY * self.curveFactor * 0.01;
// Renormalize direction after applying curve
var length = Math.sqrt(self.direction.x * self.direction.x + self.direction.y * self.direction.y);
self.direction.x /= length;
self.direction.y /= length;
}
// Move ball
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Simulate perspective by scaling the ball as it moves away
var scaleFactor = 1 - (2732 - self.y) / 2732 * 0.5;
self.scaleX = scaleFactor;
self.scaleY = scaleFactor;
// Apply gravity effect to slow down the ball
self.speed *= 0.99;
// Stop the ball if it's moving too slowly
if (self.speed < 0.5) {
self.isMoving = false;
}
};
self.reset();
return self;
});
var GameState = Container.expand(function () {
var self = Container.call(this);
self.STATES = {
AIMING: 'aiming',
POWER: 'power',
SHOOTING: 'shooting',
SAVING: 'saving',
RESULT: 'result',
GAME_OVER: 'gameOver'
};
self.currentState = self.STATES.AIMING;
self.playerTurn = true;
self.setState = function (newState) {
self.currentState = newState;
};
self.nextState = function () {
switch (self.currentState) {
case self.STATES.AIMING:
self.setState(self.STATES.POWER);
break;
case self.STATES.POWER:
self.setState(self.STATES.SHOOTING);
break;
case self.STATES.SHOOTING:
self.setState(self.STATES.RESULT);
break;
case self.STATES.SAVING:
self.setState(self.STATES.RESULT);
break;
case self.STATES.RESULT:
if (storage.currentRound >= storage.totalRounds) {
self.setState(self.STATES.GAME_OVER);
} else {
self.switchTurn();
self.setState(self.STATES.AIMING);
}
break;
}
};
self.switchTurn = function () {
self.playerTurn = !self.playerTurn;
// Increment round when both players had their turn
if (self.playerTurn) {
storage.currentRound++;
}
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
var goalGraphics = self.attachAsset('goal', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = 800;
self.height = 300;
self.reset = function () {
self.x = 1024; // Center of field horizontally
self.y = 500; // Top of field
};
self.isInGoal = function (x, y) {
return x >= self.x - self.width / 2 && x <= self.x + self.width / 2 && y >= self.y - self.height / 2 && y <= self.y + self.height / 2;
};
self.reset();
return self;
});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var goalkeeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetX = 0;
self.targetY = 0;
self.speed = 15;
self.diving = false;
self.diveDirection = 0; // -1 left, 0 center, 1 right
self.difficulty = 1;
self.reset = function () {
self.x = 1024; // Center of goal horizontally
self.y = 650; // Goal line
self.diving = false;
self.diveDirection = 0;
goalkeeperGraphics.rotation = 0;
};
self.dive = function (direction) {
if (self.diving) return;
self.diving = true;
self.diveDirection = direction;
// Rotate goalkeeper based on dive direction
if (direction < 0) {
goalkeeperGraphics.rotation = -Math.PI / 4; // 45 degrees left
} else if (direction > 0) {
goalkeeperGraphics.rotation = Math.PI / 4; // 45 degrees right
}
};
self.computerMove = function (ballX, ballY, difficulty) {
if (self.diving) return;
var predictAccuracy = Math.min(0.5 + difficulty * 0.1, 0.9); // Higher difficulty = better prediction
var randomFactor = Math.random();
if (randomFactor < predictAccuracy) {
// AI predicts correctly where the ball will go
self.targetX = ballX;
} else {
// AI makes a random guess
self.targetX = 1024 + (Math.random() * 600 - 300);
}
// Determine dive direction
var diveDirection = 0;
if (self.targetX < self.x - 100) diveDirection = -1;else if (self.targetX > self.x + 100) diveDirection = 1;
// Dive after a short reaction time based on difficulty
var reactionTime = Math.max(300 - difficulty * 30, 100);
LK.setTimeout(function () {
self.dive(diveDirection);
}, reactionTime);
};
self.update = function () {
if (!self.diving) return;
// Move goalkeeper during dive
self.x += self.speed * self.diveDirection;
// Limit goalkeeper movement within goal area
if (self.x < 700) self.x = 700;
if (self.x > 1348) self.x = 1348;
};
self.reset();
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.reset = function () {
self.x = 1024; // Center of field horizontally
self.y = 2300; // Bottom of field
};
self.celebrate = function () {
// Make player jump in celebration
tween(self, {
y: self.y - 100
}, {
duration: 400,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
y: 2300
}, {
duration: 400,
easing: tween.easeIn
});
}
});
};
self.disappointment = function () {
// Make player slump down in disappointment
tween(self, {
scaleY: 0.8
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
};
self.reset();
return self;
});
var PowerMeter = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('power_meter', {
anchorX: 0.5,
anchorY: 0.5
});
var indicator = self.attachAsset('power_indicator', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 140 // Start at bottom of power meter
});
self.power = 0;
self.increasing = true;
self.active = false;
self.startMeter = function () {
self.power = 0;
self.increasing = true;
self.active = true;
indicator.y = 140; // Reset to bottom
};
self.stopMeter = function () {
self.active = false;
return self.power;
};
self.update = function () {
if (!self.active) return;
if (self.increasing) {
self.power += 2;
if (self.power >= 100) {
self.power = 100;
self.increasing = false;
}
} else {
self.power -= 2;
if (self.power <= 0) {
self.power = 0;
self.increasing = true;
}
}
// Update indicator position
indicator.y = 140 - self.power * 280 / 100;
};
self.reset = function () {
self.x = 200;
self.y = 1366; // Center vertically
self.power = 0;
self.active = false;
indicator.y = 140; // Reset to bottom
};
self.reset();
return self;
});
var ScoreDisplay = Container.expand(function () {
var self = Container.call(this);
// Score text
self.scoreText = new Text2('0 - 0', {
size: 100,
fill: 0xFFFFFF
});
self.scoreText.anchor.set(0.5, 0);
self.addChild(self.scoreText);
// Round text
self.roundText = new Text2('Round 1/5', {
size: 60,
fill: 0xFFFFFF
});
self.roundText.anchor.set(0.5, 0);
self.roundText.y = 120;
self.addChild(self.roundText);
self.updateScore = function (playerScore, computerScore) {
self.scoreText.setText(playerScore + ' - ' + computerScore);
};
self.updateRound = function (currentRound, totalRounds) {
self.roundText.setText('Round ' + currentRound + '/' + totalRounds);
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphics = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.visible = false;
self.show = function (x, y) {
self.x = x;
self.y = y;
self.visible = true;
// Pulse animation
self.scale.set(0.7, 0.7);
tween(self.scale, {
x: 1,
y: 1
}, {
duration: 300,
easing: tween.easeOut
});
};
self.hide = function () {
self.visible = false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x33AA33
});
/****
* Game Code
****/
// Play background crowd noise
LK.playMusic('background_crowd', {
volume: 0.3
});
// Create background field
var background = LK.getAsset('bg_field', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
game.addChild(background);
// Create game objects
var gameState = new GameState();
var ball = new Ball();
var goalkeeper = new Goalkeeper();
var goal = new Goal();
var player = new Player();
var powerMeter = new PowerMeter();
var target = new Target();
// Add objects to game
game.addChild(goal);
game.addChild(goalkeeper);
game.addChild(player);
game.addChild(ball);
game.addChild(powerMeter);
game.addChild(target);
// Create UI score display
var scoreDisplay = new ScoreDisplay();
LK.gui.top.addChild(scoreDisplay);
scoreDisplay.updateScore(storage.playerScore, storage.computerScore);
scoreDisplay.updateRound(storage.currentRound, storage.totalRounds);
// Game status text
var statusText = new Text2('Tap where you want to aim', {
size: 60,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0);
LK.gui.center.addChild(statusText);
statusText.y = -200;
// Instructions text
var instructionText = new Text2('', {
size: 50,
fill: 0xFFFF00
});
instructionText.anchor.set(0.5, 0);
LK.gui.center.addChild(instructionText);
instructionText.y = -120;
// Reset the game and prepare for a new round
function resetRound() {
ball.reset();
goalkeeper.reset();
player.reset();
powerMeter.reset();
target.hide();
if (gameState.playerTurn) {
// Player is shooter
statusText.setText('Tap where you want to aim');
instructionText.setText('Choose a spot inside the goal');
gameState.setState(gameState.STATES.AIMING);
} else {
// Player is goalkeeper
statusText.setText('Get ready to save!');
instructionText.setText('Swipe in the direction you want to dive');
gameState.setState(gameState.STATES.SAVING);
// Computer shoots after a delay
LK.setTimeout(function () {
if (gameState.currentState === gameState.STATES.SAVING) {
computerShoot();
}
}, 2000);
}
scoreDisplay.updateScore(storage.playerScore, storage.computerScore);
scoreDisplay.updateRound(storage.currentRound, storage.totalRounds);
}
// Computer AI shoots the ball
function computerShoot() {
// Computer chooses a random target inside the goal
var targetX = goal.x + (Math.random() * 600 - 300);
var targetY = goal.y + (Math.random() * 200 - 100);
// Calculate a random power between
var power = 50 + Math.random() * 40;
// Calculate a random curve factor
var curve = Math.random() * 0.6 - 0.3;
// Show target briefly
target.show(targetX, targetY);
// Shoot the ball
ball.shoot(targetX, targetY, power, curve);
statusText.setText('Try to save it!');
instructionText.setText('Swipe left or right to dive');
}
// Check if the ball is saved by the goalkeeper
function checkSave() {
// Calculate distance between ball and goalkeeper
var dx = ball.x - goalkeeper.x;
var dy = ball.y - goalkeeper.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if goalkeeper saved the ball (within his reach)
var saved = distance < 150;
if (saved) {
// Play save sound
LK.getSound('save').play();
// Flash effect to show the save
LK.effects.flashObject(goalkeeper, 0xFFFFFF, 500);
statusText.setText('SAVED!');
if (gameState.playerTurn) {
// Computer saved player's shot
instructionText.setText('The goalkeeper saved your shot!');
} else {
// Player saved computer's shot
instructionText.setText('Great save!');
storage.playerScore++;
}
} else if (goal.isInGoal(ball.x, ball.y)) {
// Ball went in the goal - it's a score!
LK.getSound('goal').play();
statusText.setText('GOAL!');
if (gameState.playerTurn) {
// Player scored
instructionText.setText('You scored!');
storage.playerScore++;
player.celebrate();
} else {
// Computer scored
instructionText.setText('They scored past you!');
storage.computerScore++;
}
} else {
// Ball missed the goal
LK.getSound('miss').play();
statusText.setText('MISSED!');
if (gameState.playerTurn) {
// Player missed
instructionText.setText('Your shot went wide!');
player.disappointment();
} else {
// Computer missed
instructionText.setText('Their shot went wide!');
}
}
// Update score display
scoreDisplay.updateScore(storage.playerScore, storage.computerScore);
// Move to next state after a delay
LK.setTimeout(function () {
gameState.nextState();
if (gameState.currentState === gameState.STATES.GAME_OVER) {
endGame();
} else {
resetRound();
}
}, 2000);
}
// End the game and show final result
function endGame() {
var resultText = '';
if (storage.playerScore > storage.computerScore) {
resultText = 'You Win! ' + storage.playerScore + ' - ' + storage.computerScore;
LK.showYouWin();
} else if (storage.playerScore < storage.computerScore) {
resultText = 'You Lose! ' + storage.playerScore + ' - ' + storage.computerScore;
LK.showGameOver();
} else {
resultText = 'It\'s a Draw! ' + storage.playerScore + ' - ' + storage.computerScore;
LK.showYouWin();
}
statusText.setText(resultText);
instructionText.setText('Game Over');
// Reset game for next round
storage.playerScore = 0;
storage.computerScore = 0;
storage.currentRound = 1;
}
// Game click/tap handler
game.down = function (x, y, obj) {
if (gameState.currentState === gameState.STATES.AIMING && gameState.playerTurn) {
// Only allow aiming inside the goal
if (goal.isInGoal(x, y)) {
target.show(x, y);
statusText.setText('Set your power');
instructionText.setText('Tap to stop the power meter');
gameState.nextState();
powerMeter.startMeter();
}
} else if (gameState.currentState === gameState.STATES.POWER && gameState.playerTurn) {
var power = powerMeter.stopMeter();
statusText.setText('Shooting!');
instructionText.setText('');
// Shoot the ball with random curve
var curve = Math.random() * 0.4 - 0.2;
ball.shoot(target.x, target.y, power, curve);
// Computer goalkeeper tries to save
goalkeeper.computerMove(target.x, target.y, storage.difficulty);
gameState.nextState();
} else if (gameState.currentState === gameState.STATES.SAVING && !gameState.playerTurn) {
// Record start of swipe for goalkeeper dive
game.swipeStartX = x;
game.swipeStartY = y;
}
};
// Game drag release handler
game.up = function (x, y, obj) {
if (gameState.currentState === gameState.STATES.SAVING && !gameState.playerTurn && game.swipeStartX) {
// Calculate swipe direction
var swipeDx = x - game.swipeStartX;
var swipeThreshold = 50;
var diveDirection = 0;
if (swipeDx < -swipeThreshold) diveDirection = -1;else if (swipeDx > swipeThreshold) diveDirection = 1;
// Make goalkeeper dive
goalkeeper.dive(diveDirection);
// Reset swipe tracking
game.swipeStartX = null;
}
};
// Main game update loop
game.update = function () {
// Update game objects
ball.update();
goalkeeper.update();
powerMeter.update();
// Handle state-specific logic
if (gameState.currentState === gameState.STATES.SHOOTING || gameState.currentState === gameState.STATES.SAVING) {
// Check if ball has stopped moving
if (ball.isMoving === false && ball.y < 1000) {
gameState.setState(gameState.STATES.RESULT);
checkSave();
}
// Check if ball has gone far off screen
if (ball.y < -200 || ball.x < -200 || ball.x > 2248) {
ball.isMoving = false;
gameState.setState(gameState.STATES.RESULT);
checkSave();
}
}
};
// Initialize the game with first round
resetRound(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,613 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ playerScore: 0,
+ computerScore: 0,
+ currentRound: 1,
+ totalRounds: 5,
+ difficulty: 1
+});
+
+/****
+* Classes
+****/
+var Ball = Container.expand(function () {
+ var self = Container.call(this);
+ var ballGraphics = self.attachAsset('ball', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 0;
+ self.direction = {
+ x: 0,
+ y: 0
+ };
+ self.isMoving = false;
+ self.curveFactor = 0;
+ self.reset = function () {
+ self.x = 1024; // Center of field horizontally
+ self.y = 2200; // Bottom of field where player stands
+ self.isMoving = false;
+ self.speed = 0;
+ self.direction = {
+ x: 0,
+ y: 0
+ };
+ self.curveFactor = 0;
+ self.scaleX = 1;
+ self.scaleY = 1;
+ };
+ self.shoot = function (targetX, targetY, power, curve) {
+ if (self.isMoving) return;
+ // Calculate direction vector
+ self.direction.x = targetX - self.x;
+ self.direction.y = targetY - self.y;
+ // Normalize direction vector
+ var length = Math.sqrt(self.direction.x * self.direction.x + self.direction.y * self.direction.y);
+ self.direction.x /= length;
+ self.direction.y /= length;
+ // Set speed based on power (0-100)
+ self.speed = 5 + power * 15 / 100;
+ // Set curve factor (-1 to 1)
+ self.curveFactor = curve;
+ self.isMoving = true;
+ // Play kick sound
+ LK.getSound('kick').play();
+ };
+ self.update = function () {
+ if (!self.isMoving) return;
+ // Apply curve to direction (simulating curved shot)
+ if (self.curveFactor !== 0) {
+ var perpX = -self.direction.y;
+ var perpY = self.direction.x;
+ self.direction.x += perpX * self.curveFactor * 0.01;
+ self.direction.y += perpY * self.curveFactor * 0.01;
+ // Renormalize direction after applying curve
+ var length = Math.sqrt(self.direction.x * self.direction.x + self.direction.y * self.direction.y);
+ self.direction.x /= length;
+ self.direction.y /= length;
+ }
+ // Move ball
+ self.x += self.direction.x * self.speed;
+ self.y += self.direction.y * self.speed;
+ // Simulate perspective by scaling the ball as it moves away
+ var scaleFactor = 1 - (2732 - self.y) / 2732 * 0.5;
+ self.scaleX = scaleFactor;
+ self.scaleY = scaleFactor;
+ // Apply gravity effect to slow down the ball
+ self.speed *= 0.99;
+ // Stop the ball if it's moving too slowly
+ if (self.speed < 0.5) {
+ self.isMoving = false;
+ }
+ };
+ self.reset();
+ return self;
+});
+var GameState = Container.expand(function () {
+ var self = Container.call(this);
+ self.STATES = {
+ AIMING: 'aiming',
+ POWER: 'power',
+ SHOOTING: 'shooting',
+ SAVING: 'saving',
+ RESULT: 'result',
+ GAME_OVER: 'gameOver'
+ };
+ self.currentState = self.STATES.AIMING;
+ self.playerTurn = true;
+ self.setState = function (newState) {
+ self.currentState = newState;
+ };
+ self.nextState = function () {
+ switch (self.currentState) {
+ case self.STATES.AIMING:
+ self.setState(self.STATES.POWER);
+ break;
+ case self.STATES.POWER:
+ self.setState(self.STATES.SHOOTING);
+ break;
+ case self.STATES.SHOOTING:
+ self.setState(self.STATES.RESULT);
+ break;
+ case self.STATES.SAVING:
+ self.setState(self.STATES.RESULT);
+ break;
+ case self.STATES.RESULT:
+ if (storage.currentRound >= storage.totalRounds) {
+ self.setState(self.STATES.GAME_OVER);
+ } else {
+ self.switchTurn();
+ self.setState(self.STATES.AIMING);
+ }
+ break;
+ }
+ };
+ self.switchTurn = function () {
+ self.playerTurn = !self.playerTurn;
+ // Increment round when both players had their turn
+ if (self.playerTurn) {
+ storage.currentRound++;
+ }
+ };
+ return self;
+});
+var Goal = Container.expand(function () {
+ var self = Container.call(this);
+ var goalGraphics = self.attachAsset('goal', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = 800;
+ self.height = 300;
+ self.reset = function () {
+ self.x = 1024; // Center of field horizontally
+ self.y = 500; // Top of field
+ };
+ self.isInGoal = function (x, y) {
+ return x >= self.x - self.width / 2 && x <= self.x + self.width / 2 && y >= self.y - self.height / 2 && y <= self.y + self.height / 2;
+ };
+ self.reset();
+ return self;
+});
+var Goalkeeper = Container.expand(function () {
+ var self = Container.call(this);
+ var goalkeeperGraphics = self.attachAsset('goalkeeper', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.targetX = 0;
+ self.targetY = 0;
+ self.speed = 15;
+ self.diving = false;
+ self.diveDirection = 0; // -1 left, 0 center, 1 right
+ self.difficulty = 1;
+ self.reset = function () {
+ self.x = 1024; // Center of goal horizontally
+ self.y = 650; // Goal line
+ self.diving = false;
+ self.diveDirection = 0;
+ goalkeeperGraphics.rotation = 0;
+ };
+ self.dive = function (direction) {
+ if (self.diving) return;
+ self.diving = true;
+ self.diveDirection = direction;
+ // Rotate goalkeeper based on dive direction
+ if (direction < 0) {
+ goalkeeperGraphics.rotation = -Math.PI / 4; // 45 degrees left
+ } else if (direction > 0) {
+ goalkeeperGraphics.rotation = Math.PI / 4; // 45 degrees right
+ }
+ };
+ self.computerMove = function (ballX, ballY, difficulty) {
+ if (self.diving) return;
+ var predictAccuracy = Math.min(0.5 + difficulty * 0.1, 0.9); // Higher difficulty = better prediction
+ var randomFactor = Math.random();
+ if (randomFactor < predictAccuracy) {
+ // AI predicts correctly where the ball will go
+ self.targetX = ballX;
+ } else {
+ // AI makes a random guess
+ self.targetX = 1024 + (Math.random() * 600 - 300);
+ }
+ // Determine dive direction
+ var diveDirection = 0;
+ if (self.targetX < self.x - 100) diveDirection = -1;else if (self.targetX > self.x + 100) diveDirection = 1;
+ // Dive after a short reaction time based on difficulty
+ var reactionTime = Math.max(300 - difficulty * 30, 100);
+ LK.setTimeout(function () {
+ self.dive(diveDirection);
+ }, reactionTime);
+ };
+ self.update = function () {
+ if (!self.diving) return;
+ // Move goalkeeper during dive
+ self.x += self.speed * self.diveDirection;
+ // Limit goalkeeper movement within goal area
+ if (self.x < 700) self.x = 700;
+ if (self.x > 1348) self.x = 1348;
+ };
+ self.reset();
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var playerGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.reset = function () {
+ self.x = 1024; // Center of field horizontally
+ self.y = 2300; // Bottom of field
+ };
+ self.celebrate = function () {
+ // Make player jump in celebration
+ tween(self, {
+ y: self.y - 100
+ }, {
+ duration: 400,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ y: 2300
+ }, {
+ duration: 400,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ self.disappointment = function () {
+ // Make player slump down in disappointment
+ tween(self, {
+ scaleY: 0.8
+ }, {
+ duration: 500,
+ easing: tween.easeOut,
+ onFinish: function onFinish() {
+ tween(self, {
+ scaleY: 1
+ }, {
+ duration: 500,
+ easing: tween.easeIn
+ });
+ }
+ });
+ };
+ self.reset();
+ return self;
+});
+var PowerMeter = Container.expand(function () {
+ var self = Container.call(this);
+ var background = self.attachAsset('power_meter', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var indicator = self.attachAsset('power_indicator', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 140 // Start at bottom of power meter
+ });
+ self.power = 0;
+ self.increasing = true;
+ self.active = false;
+ self.startMeter = function () {
+ self.power = 0;
+ self.increasing = true;
+ self.active = true;
+ indicator.y = 140; // Reset to bottom
+ };
+ self.stopMeter = function () {
+ self.active = false;
+ return self.power;
+ };
+ self.update = function () {
+ if (!self.active) return;
+ if (self.increasing) {
+ self.power += 2;
+ if (self.power >= 100) {
+ self.power = 100;
+ self.increasing = false;
+ }
+ } else {
+ self.power -= 2;
+ if (self.power <= 0) {
+ self.power = 0;
+ self.increasing = true;
+ }
+ }
+ // Update indicator position
+ indicator.y = 140 - self.power * 280 / 100;
+ };
+ self.reset = function () {
+ self.x = 200;
+ self.y = 1366; // Center vertically
+ self.power = 0;
+ self.active = false;
+ indicator.y = 140; // Reset to bottom
+ };
+ self.reset();
+ return self;
+});
+var ScoreDisplay = Container.expand(function () {
+ var self = Container.call(this);
+ // Score text
+ self.scoreText = new Text2('0 - 0', {
+ size: 100,
+ fill: 0xFFFFFF
+ });
+ self.scoreText.anchor.set(0.5, 0);
+ self.addChild(self.scoreText);
+ // Round text
+ self.roundText = new Text2('Round 1/5', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ self.roundText.anchor.set(0.5, 0);
+ self.roundText.y = 120;
+ self.addChild(self.roundText);
+ self.updateScore = function (playerScore, computerScore) {
+ self.scoreText.setText(playerScore + ' - ' + computerScore);
+ };
+ self.updateRound = function (currentRound, totalRounds) {
+ self.roundText.setText('Round ' + currentRound + '/' + totalRounds);
+ };
+ return self;
+});
+var Target = Container.expand(function () {
+ var self = Container.call(this);
+ var targetGraphics = self.attachAsset('target', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.visible = false;
+ self.show = function (x, y) {
+ self.x = x;
+ self.y = y;
+ self.visible = true;
+ // Pulse animation
+ self.scale.set(0.7, 0.7);
+ tween(self.scale, {
+ x: 1,
+ y: 1
+ }, {
+ duration: 300,
+ easing: tween.easeOut
+ });
+ };
+ self.hide = function () {
+ self.visible = false;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x33AA33
+});
+
+/****
+* Game Code
+****/
+// Play background crowd noise
+LK.playMusic('background_crowd', {
+ volume: 0.3
+});
+// Create background field
+var background = LK.getAsset('bg_field', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 1024,
+ y: 1366
+});
+game.addChild(background);
+// Create game objects
+var gameState = new GameState();
+var ball = new Ball();
+var goalkeeper = new Goalkeeper();
+var goal = new Goal();
+var player = new Player();
+var powerMeter = new PowerMeter();
+var target = new Target();
+// Add objects to game
+game.addChild(goal);
+game.addChild(goalkeeper);
+game.addChild(player);
+game.addChild(ball);
+game.addChild(powerMeter);
+game.addChild(target);
+// Create UI score display
+var scoreDisplay = new ScoreDisplay();
+LK.gui.top.addChild(scoreDisplay);
+scoreDisplay.updateScore(storage.playerScore, storage.computerScore);
+scoreDisplay.updateRound(storage.currentRound, storage.totalRounds);
+// Game status text
+var statusText = new Text2('Tap where you want to aim', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+statusText.anchor.set(0.5, 0);
+LK.gui.center.addChild(statusText);
+statusText.y = -200;
+// Instructions text
+var instructionText = new Text2('', {
+ size: 50,
+ fill: 0xFFFF00
+});
+instructionText.anchor.set(0.5, 0);
+LK.gui.center.addChild(instructionText);
+instructionText.y = -120;
+// Reset the game and prepare for a new round
+function resetRound() {
+ ball.reset();
+ goalkeeper.reset();
+ player.reset();
+ powerMeter.reset();
+ target.hide();
+ if (gameState.playerTurn) {
+ // Player is shooter
+ statusText.setText('Tap where you want to aim');
+ instructionText.setText('Choose a spot inside the goal');
+ gameState.setState(gameState.STATES.AIMING);
+ } else {
+ // Player is goalkeeper
+ statusText.setText('Get ready to save!');
+ instructionText.setText('Swipe in the direction you want to dive');
+ gameState.setState(gameState.STATES.SAVING);
+ // Computer shoots after a delay
+ LK.setTimeout(function () {
+ if (gameState.currentState === gameState.STATES.SAVING) {
+ computerShoot();
+ }
+ }, 2000);
+ }
+ scoreDisplay.updateScore(storage.playerScore, storage.computerScore);
+ scoreDisplay.updateRound(storage.currentRound, storage.totalRounds);
+}
+// Computer AI shoots the ball
+function computerShoot() {
+ // Computer chooses a random target inside the goal
+ var targetX = goal.x + (Math.random() * 600 - 300);
+ var targetY = goal.y + (Math.random() * 200 - 100);
+ // Calculate a random power between
+ var power = 50 + Math.random() * 40;
+ // Calculate a random curve factor
+ var curve = Math.random() * 0.6 - 0.3;
+ // Show target briefly
+ target.show(targetX, targetY);
+ // Shoot the ball
+ ball.shoot(targetX, targetY, power, curve);
+ statusText.setText('Try to save it!');
+ instructionText.setText('Swipe left or right to dive');
+}
+// Check if the ball is saved by the goalkeeper
+function checkSave() {
+ // Calculate distance between ball and goalkeeper
+ var dx = ball.x - goalkeeper.x;
+ var dy = ball.y - goalkeeper.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ // Check if goalkeeper saved the ball (within his reach)
+ var saved = distance < 150;
+ if (saved) {
+ // Play save sound
+ LK.getSound('save').play();
+ // Flash effect to show the save
+ LK.effects.flashObject(goalkeeper, 0xFFFFFF, 500);
+ statusText.setText('SAVED!');
+ if (gameState.playerTurn) {
+ // Computer saved player's shot
+ instructionText.setText('The goalkeeper saved your shot!');
+ } else {
+ // Player saved computer's shot
+ instructionText.setText('Great save!');
+ storage.playerScore++;
+ }
+ } else if (goal.isInGoal(ball.x, ball.y)) {
+ // Ball went in the goal - it's a score!
+ LK.getSound('goal').play();
+ statusText.setText('GOAL!');
+ if (gameState.playerTurn) {
+ // Player scored
+ instructionText.setText('You scored!');
+ storage.playerScore++;
+ player.celebrate();
+ } else {
+ // Computer scored
+ instructionText.setText('They scored past you!');
+ storage.computerScore++;
+ }
+ } else {
+ // Ball missed the goal
+ LK.getSound('miss').play();
+ statusText.setText('MISSED!');
+ if (gameState.playerTurn) {
+ // Player missed
+ instructionText.setText('Your shot went wide!');
+ player.disappointment();
+ } else {
+ // Computer missed
+ instructionText.setText('Their shot went wide!');
+ }
+ }
+ // Update score display
+ scoreDisplay.updateScore(storage.playerScore, storage.computerScore);
+ // Move to next state after a delay
+ LK.setTimeout(function () {
+ gameState.nextState();
+ if (gameState.currentState === gameState.STATES.GAME_OVER) {
+ endGame();
+ } else {
+ resetRound();
+ }
+ }, 2000);
+}
+// End the game and show final result
+function endGame() {
+ var resultText = '';
+ if (storage.playerScore > storage.computerScore) {
+ resultText = 'You Win! ' + storage.playerScore + ' - ' + storage.computerScore;
+ LK.showYouWin();
+ } else if (storage.playerScore < storage.computerScore) {
+ resultText = 'You Lose! ' + storage.playerScore + ' - ' + storage.computerScore;
+ LK.showGameOver();
+ } else {
+ resultText = 'It\'s a Draw! ' + storage.playerScore + ' - ' + storage.computerScore;
+ LK.showYouWin();
+ }
+ statusText.setText(resultText);
+ instructionText.setText('Game Over');
+ // Reset game for next round
+ storage.playerScore = 0;
+ storage.computerScore = 0;
+ storage.currentRound = 1;
+}
+// Game click/tap handler
+game.down = function (x, y, obj) {
+ if (gameState.currentState === gameState.STATES.AIMING && gameState.playerTurn) {
+ // Only allow aiming inside the goal
+ if (goal.isInGoal(x, y)) {
+ target.show(x, y);
+ statusText.setText('Set your power');
+ instructionText.setText('Tap to stop the power meter');
+ gameState.nextState();
+ powerMeter.startMeter();
+ }
+ } else if (gameState.currentState === gameState.STATES.POWER && gameState.playerTurn) {
+ var power = powerMeter.stopMeter();
+ statusText.setText('Shooting!');
+ instructionText.setText('');
+ // Shoot the ball with random curve
+ var curve = Math.random() * 0.4 - 0.2;
+ ball.shoot(target.x, target.y, power, curve);
+ // Computer goalkeeper tries to save
+ goalkeeper.computerMove(target.x, target.y, storage.difficulty);
+ gameState.nextState();
+ } else if (gameState.currentState === gameState.STATES.SAVING && !gameState.playerTurn) {
+ // Record start of swipe for goalkeeper dive
+ game.swipeStartX = x;
+ game.swipeStartY = y;
+ }
+};
+// Game drag release handler
+game.up = function (x, y, obj) {
+ if (gameState.currentState === gameState.STATES.SAVING && !gameState.playerTurn && game.swipeStartX) {
+ // Calculate swipe direction
+ var swipeDx = x - game.swipeStartX;
+ var swipeThreshold = 50;
+ var diveDirection = 0;
+ if (swipeDx < -swipeThreshold) diveDirection = -1;else if (swipeDx > swipeThreshold) diveDirection = 1;
+ // Make goalkeeper dive
+ goalkeeper.dive(diveDirection);
+ // Reset swipe tracking
+ game.swipeStartX = null;
+ }
+};
+// Main game update loop
+game.update = function () {
+ // Update game objects
+ ball.update();
+ goalkeeper.update();
+ powerMeter.update();
+ // Handle state-specific logic
+ if (gameState.currentState === gameState.STATES.SHOOTING || gameState.currentState === gameState.STATES.SAVING) {
+ // Check if ball has stopped moving
+ if (ball.isMoving === false && ball.y < 1000) {
+ gameState.setState(gameState.STATES.RESULT);
+ checkSave();
+ }
+ // Check if ball has gone far off screen
+ if (ball.y < -200 || ball.x < -200 || ball.x > 2248) {
+ ball.isMoving = false;
+ gameState.setState(gameState.STATES.RESULT);
+ checkSave();
+ }
+ }
+};
+// Initialize the game with first round
+resetRound();
\ No newline at end of file
soccer ball 2d ingame asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows
soccer goal 2d ingame asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows
male soccer goalkeeper with hands up and not holding ball 2d ingame asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows
target logo 2d ingame asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows
soccer field 2d ingame asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows
male soccer striker not holding ball 2d ingame asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows
spectator character 2d in game asset high contrast no shadows. In-Game asset. 2d. High contrast. No shadows