User prompt
Please fix the bug: 'Error: Invalid value. Only literals or 1-level deep objects/arrays containing literals are allowed.' in or related to this line: 'storage.leaderboard = leaderboard;' Line Number: 574 βͺπ‘ Consider importing and using the following plugins: @upit/storage.v1
User prompt
ask players to insert their names in the beginning and keep track of every player that played the game and make a leaderboard with the best 10 players name and scores βͺπ‘ Consider importing and using the following plugins: @upit/storage.v1
User prompt
player can choose the spinning level between -20 to 20
User prompt
goalkeeper should sometimes saves the ball βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the goalkeeper saves the shots that are close to the middle of the goal. only the balls that goes to the close to the corner of the goals will not be saved by the goalkeeper βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
bring the goalkeeper in front of the goal
User prompt
goalkeeper should return to its initial position after each shot βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
goalkeeper moves faster to save the goal and sometimes the goalkeeper will save βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
goalkeeper now moves towards the balls direction to save from scoring βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
bring the defenders in front of the goal, they shouldnt stay inside of the goal
User prompt
adjust the scoring zone in line with the goal zone, only if the ball touches to goal or the inside lines it will be counted as a score
User prompt
can you adjust goalkeeper to lower of the screen like he is standing in front of the goal
User prompt
I want lighter pink
User prompt
I changed my mind. I want pink background
User prompt
I want a little darker green
User prompt
can you change background color to lighter green
User prompt
move the buttons for spin to a little bit left and right just to adjust according to the text
User prompt
make all the texts and buttons bigger by 25%
User prompt
make all the texts and buttons bigger by x2
User prompt
can you add to the instruction page the info of "inside of the lines are counted as scores as well"
User prompt
can you add personal best score to the game screen? so that player can compete with its personal best βͺπ‘ Consider importing and using the following plugins: @upit/storage.v1
User prompt
make the 2 defenders stay at the same place side by side, but make the other 2 players randomly
User prompt
starting from to 10th round put 1 random defender in front of the goal
User prompt
starting from to 10th round put 1 random defender close the goal
User prompt
change button press mechanism to clicking the arrows to change spin levels
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.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;
self.friction = 0.98;
self.isMoving = false;
self.spinForce = 0;
self.spinDecay = 0.98;
self.shoot = function (power, angle, spin) {
self.velocityX = Math.cos(angle) * power;
self.velocityY = Math.sin(angle) * power;
self.spinForce = spin || 0;
self.isMoving = true;
LK.getSound('kick').play();
};
self.reset = function () {
self.x = ballStartX;
self.y = ballStartY;
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
self.spinForce = 0;
};
self.update = function () {
if (self.isMoving) {
// Apply spin curve effect
if (self.spinForce !== 0) {
// Calculate perpendicular force to current velocity for curve
var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
if (speed > 0) {
var normalX = -self.velocityY / speed;
var normalY = self.velocityX / speed;
self.velocityX += normalX * self.spinForce * 0.1;
self.velocityY += normalY * self.spinForce * 0.1;
}
// Decay spin over time
self.spinForce *= self.spinDecay;
}
self.x += self.velocityX;
self.y += self.velocityY;
// No friction applied - ball maintains constant velocity
// Bounds checking
if (self.x < 0 || self.x > 2048 || self.y > 2732) {
self.isMoving = false;
ballMissed();
}
}
};
return self;
});
var Defender = Container.expand(function () {
var self = Container.call(this);
var defenderGraphics = self.attachAsset('defender', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 1.0
});
return self;
});
var TrajectoryDot = Container.expand(function () {
var self = Container.call(this);
var dotGraphics = self.attachAsset('trajectory', {
anchorX: 0.5,
anchorY: 0.5
});
dotGraphics.alpha = 0.6;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x90EE90
});
/****
* Game Code
****/
// Game variables
var currentRound = 1;
var attemptsLeft = 3;
var ballStartX = 1024;
var ballStartY = 2500;
var goalX = 1024;
var goalY = 400;
var isAiming = false;
var dragStartX = 0;
var dragStartY = 0;
var dragCurrentX = 0;
var dragCurrentY = 0;
var trajectoryDots = [];
var defenders = [];
// Swipe tracking variables
var swipePath = [];
var swipeStartTime = 0;
var swipeSpeed = 0;
var swipeCurve = 0;
var maxSwipePoints = 10;
// Create grass field
var grass = game.addChild(LK.getAsset('grass', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Create goal structure
var goal = game.addChild(LK.getAsset('goal', {
anchorX: 0.5,
anchorY: 0.5,
x: goalX,
y: goalY + 100
}));
goal.alpha = 0.3; // Make goal semi-transparent so we can see the ball
// Create goalkeeper
var goalkeeper = game.addChild(new Goalkeeper());
goalkeeper.x = goalX;
goalkeeper.y = goalY + 180;
// Create ball
var ball = game.addChild(new Ball());
ball.reset();
// UI Elements
var roundText = new Text2('Round: 1', {
size: 100,
fill: 0xFFFFFF
});
roundText.anchor.set(0.5, 0);
LK.gui.top.addChild(roundText);
var attemptsText = new Text2('Attempts: 3', {
size: 75,
fill: 0xFFFFFF
});
attemptsText.anchor.set(1.0, 0);
LK.gui.topRight.addChild(attemptsText);
var personalBest = storage.personalBest || 0;
var personalBestText = new Text2('Best: ' + personalBest, {
size: 75,
fill: 0x00FF00
});
personalBestText.anchor.set(0, 0);
LK.gui.topLeft.addChild(personalBestText);
personalBestText.x = 120; // Move away from platform menu icon
var powerText = new Text2('', {
size: 62,
fill: 0xFFFF00
});
powerText.anchor.set(0.5, 0.5);
game.addChild(powerText);
var curveText = new Text2('Spin: 0', {
size: 75,
fill: 0xFFFFFF
});
curveText.anchor.set(0.5, 0.5);
curveText.x = 1024;
curveText.y = 200;
game.addChild(curveText);
var selectedCurve = 0;
var maxCurve = 8;
var curveValues = [-8, -6, -4, -2, -1, 0, 1, 2, 4, 6, 8];
var curveIndex = 5; // Start at 0 curve
var fixedSpeed = 35;
// Create curve adjustment buttons
var leftCurveButton = new Text2('<', {
size: 125,
fill: 0xFFFF00
});
leftCurveButton.anchor.set(0.5, 0.5);
leftCurveButton.x = 850;
leftCurveButton.y = 200;
game.addChild(leftCurveButton);
var rightCurveButton = new Text2('>', {
size: 125,
fill: 0xFFFF00
});
rightCurveButton.anchor.set(0.5, 0.5);
rightCurveButton.x = 1198;
rightCurveButton.y = 200;
game.addChild(rightCurveButton);
// Function to update curve display
function updateCurveDisplay() {
selectedCurve = curveValues[curveIndex];
if (selectedCurve === 0) {
curveText.setText('Spin: 0');
} else {
curveText.setText('Spin: ' + (selectedCurve > 0 ? '+' : '') + selectedCurve);
}
console.log('Curve updated to:', selectedCurve, 'Index:', curveIndex);
}
// Initialize curve display
updateCurveDisplay();
// Initialize defenders for current round
function setupRound() {
// Clear existing defenders
for (var i = 0; i < defenders.length; i++) {
defenders[i].destroy();
}
defenders = [];
// Add defenders based on round
var numDefenders = Math.min(currentRound - 1, 4);
for (var i = 0; i < numDefenders; i++) {
var defender = game.addChild(new Defender());
if (i < 2) {
// First 2 defenders stay side by side in fixed positions
var spacing = 120;
var startX = goalX - spacing / 2;
defender.x = startX + i * spacing;
defender.y = goalY + 300 + currentRound * 50;
} else {
// Other 2 defenders are placed randomly
var randomX = goalX + (Math.random() - 0.5) * 600; // Random X within a reasonable area
var randomY = goalY + 250 + Math.random() * 300; // Random Y in front of goal
defender.x = randomX;
defender.y = randomY;
}
defenders.push(defender);
}
// Starting from round 10, add 1 random defender in front of the goal
if (currentRound >= 10) {
var randomDefender = game.addChild(new Defender());
// Random position in front of goal area
var randomX = goalX + (Math.random() - 0.5) * 800; // Random X within goal width area
var randomY = goalY + 200 + Math.random() * 200; // Random Y in front of goal
randomDefender.x = randomX;
randomDefender.y = randomY;
defenders.push(randomDefender);
}
roundText.setText('Round: ' + currentRound);
attemptsText.setText('Attempts: ' + attemptsLeft);
}
// Create trajectory preview
function createTrajectoryPreview(power, angle, spin) {
// Clear existing dots
for (var i = 0; i < trajectoryDots.length; i++) {
trajectoryDots[i].destroy();
}
trajectoryDots = [];
// Calculate trajectory points
var steps = 15;
var stepTime = 0.8;
var tempVelX = Math.cos(angle) * power * 0.7;
var tempVelY = Math.sin(angle) * power * 0.7;
var tempX = ball.x;
var tempY = ball.y;
var tempSpin = spin || 0;
for (var i = 0; i < steps; i++) {
// Apply spin curve effect in preview
if (tempSpin !== 0) {
var speed = Math.sqrt(tempVelX * tempVelX + tempVelY * tempVelY);
if (speed > 0) {
var normalX = -tempVelY / speed;
var normalY = tempVelX / speed;
tempVelX += normalX * tempSpin * 0.1;
tempVelY += normalY * tempSpin * 0.1;
}
tempSpin *= 0.98;
}
tempX += tempVelX * stepTime;
tempY += tempVelY * stepTime;
// No gravity applied to trajectory preview
tempVelX *= 0.98;
tempVelY *= 0.98;
if (tempY > 2732 || tempX < 0 || tempX > 2048) break;
var dot = game.addChild(new TrajectoryDot());
dot.x = tempX;
dot.y = tempY;
trajectoryDots.push(dot);
}
}
// Clear trajectory preview
function clearTrajectoryPreview() {
for (var i = 0; i < trajectoryDots.length; i++) {
trajectoryDots[i].destroy();
}
trajectoryDots = [];
}
// Calculate curve from swipe path
function calculateSwipeCurve() {
if (swipePath.length < 3) return 0;
var totalCurvature = 0;
var validSegments = 0;
var curvatureSum = 0;
var pathLength = 0;
// Calculate curvature at each point in the path
for (var i = 1; i < swipePath.length - 1; i++) {
var p1 = swipePath[i - 1];
var p2 = swipePath[i];
var p3 = swipePath[i + 1];
// Calculate vectors
var v1x = p2.x - p1.x;
var v1y = p2.y - p1.y;
var v2x = p3.x - p2.x;
var v2y = p3.y - p2.y;
// Calculate cross product to determine curve direction
var crossProduct = v1x * v2y - v1y * v2x;
// Calculate magnitudes
var mag1 = Math.sqrt(v1x * v1x + v1y * v1y);
var mag2 = Math.sqrt(v2x * v2x + v2y * v2y);
if (mag1 > 5 && mag2 > 5) {
// Only consider significant movements
curvatureSum += crossProduct / (mag1 * mag2);
validSegments++;
pathLength += mag1;
}
}
if (validSegments > 0) {
totalCurvature = curvatureSum / validSegments;
// Scale based on path length and speed
var lengthFactor = Math.min(pathLength / 200, 2);
var speedFactor = Math.min(swipeSpeed / 500, 2);
var finalCurve = totalCurvature * lengthFactor * speedFactor * 15;
return Math.max(-10, Math.min(10, finalCurve));
}
return 0;
}
// Calculate swipe speed
function calculateSwipeSpeed() {
if (swipePath.length < 2) return 0;
var totalDistance = 0;
var totalTime = 0;
for (var i = 1; i < swipePath.length; i++) {
var p1 = swipePath[i - 1];
var p2 = swipePath[i];
var dx = p2.x - p1.x;
var dy = p2.y - p1.y;
totalDistance += Math.sqrt(dx * dx + dy * dy);
totalTime += p2.time - p1.time;
}
return totalTime > 0 ? totalDistance / totalTime * 1000 : 0;
}
// Ball collision detection
function checkCollisions() {
// Check goalkeeper collision first - this prevents scoring
if (ball.intersects(goalkeeper)) {
ball.isMoving = false;
LK.getSound('save').play();
LK.effects.flashObject(goalkeeper, 0xffff00, 500);
ballMissed();
return;
}
// Check goal scoring - ball must be inside goal area including side lines
var goalLeft = goalX - 500; // Left side line of goal
var goalRight = goalX + 500; // Right side line of goal
var goalTop = goalY - 155; // Top of goal
var goalBottom = goalY + 155; // Bottom of goal
if (ball.x >= goalLeft && ball.x <= goalRight && ball.y >= goalTop && ball.y <= goalBottom) {
// Goal scored! Ball touched inside goal area or side lines
ball.isMoving = false;
LK.getSound('goal').play();
LK.effects.flashScreen(0x00ff00, 500);
LK.setScore(LK.getScore() + 1);
// Check and update personal best
var currentScore = LK.getScore();
if (currentScore > personalBest) {
personalBest = currentScore;
storage.personalBest = personalBest;
personalBestText.setText('Best: ' + personalBest);
LK.effects.flashObject(personalBestText, 0xFFFF00, 1000);
}
currentRound++;
// Reset attempts for next round
attemptsLeft = 3;
LK.setTimeout(function () {
ball.reset();
setupRound();
}, 1000);
return;
}
// Check defender collisions
for (var i = 0; i < defenders.length; i++) {
if (ball.intersects(defenders[i])) {
ball.isMoving = false;
LK.effects.flashObject(defenders[i], 0xff0000, 500);
ballMissed();
return;
}
}
// Goal structure collision removed to allow ball to pass through for scoring
}
function ballMissed() {
attemptsLeft--;
attemptsText.setText('Attempts: ' + attemptsLeft);
if (attemptsLeft <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver(); // Show game over screen and reset game
}, 1500);
} else {
LK.setTimeout(function () {
ball.reset();
}, 1000);
}
}
// Game controls are now defined as variables above
game.update = function () {
if (ball.isMoving) {
checkCollisions();
}
};
// Game instructions
var instructionsText = new Text2('Swipe to aim and shoot!\nUse < > buttons to adjust spin.\nSwipe direction sets aim, spin is manual.\nInside of the lines are counted as scores as well.', {
size: 75,
fill: 0xFFFFFF,
align: 'center'
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 1366;
game.addChild(instructionsText);
var startButton = new Text2('TAP TO START', {
size: 100,
fill: 0x00FF00
});
startButton.anchor.set(0.5, 0.5);
startButton.x = 1024;
startButton.y = 1600;
game.addChild(startButton);
var gameStarted = false;
// Store the actual game control functions
var originalDown = function originalDown(x, y, obj) {
if (!ball.isMoving && ball.y > 2000) {
isAiming = true;
dragStartX = x;
dragStartY = y;
swipePath = [{
x: x,
y: y,
time: Date.now()
}];
swipeStartTime = Date.now();
}
};
var originalMove = function originalMove(x, y, obj) {
if (isAiming && !ball.isMoving) {
dragCurrentX = x;
dragCurrentY = y;
// Track swipe path
var currentTime = Date.now();
swipePath.push({
x: x,
y: y,
time: currentTime
});
// Keep only recent points
if (swipePath.length > maxSwipePoints) {
swipePath.shift();
}
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var power = fixedSpeed;
var angle = Math.atan2(-deltaY, deltaX);
powerText.x = ball.x;
powerText.y = ball.y - 100;
powerText.setText('');
// Show trajectory with current manual curve setting
createTrajectoryPreview(power, angle, selectedCurve);
}
};
var originalUp = function originalUp(x, y, obj) {
if (isAiming && !ball.isMoving) {
var deltaX = x - dragStartX;
var deltaY = y - dragStartY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 20) {
var power = fixedSpeed;
var angle = Math.atan2(-deltaY, deltaX);
// Use manually selected curve
var spin = selectedCurve;
ball.shoot(power, angle, spin);
}
isAiming = false;
powerText.setText('');
clearTrajectoryPreview();
// Clear swipe path
swipePath = [];
}
};
// Add click handlers to curve buttons
leftCurveButton.down = function (x, y, obj) {
if (gameStarted && !ball.isMoving) {
if (curveIndex > 0) {
curveIndex--;
updateCurveDisplay();
LK.effects.flashObject(leftCurveButton, 0x00ff00, 200);
}
}
};
rightCurveButton.down = function (x, y, obj) {
if (gameStarted && !ball.isMoving) {
if (curveIndex < curveValues.length - 1) {
curveIndex++;
updateCurveDisplay();
LK.effects.flashObject(rightCurveButton, 0x00ff00, 200);
}
}
};
// Override game controls until game starts
game.down = function (x, y, obj) {
if (!gameStarted) {
// Start the game
gameStarted = true;
instructionsText.destroy();
startButton.destroy();
// Restore original controls
game.down = originalDown;
game.move = originalMove;
game.up = originalUp;
// Initialize first round
setupRound();
// Call the original down handler for this event
originalDown(x, y, obj);
return;
}
};
game.move = function (x, y, obj) {
// Do nothing until game starts
};
game.up = function (x, y, obj) {
// Do nothing until game starts
}; ===================================================================
--- original.js
+++ change.js
@@ -91,9 +91,9 @@
/****
* Initialize Game
****/
var game = new LK.Game({
- backgroundColor: 0x228B22
+ backgroundColor: 0x90EE90
});
/****
* Game Code