User prompt
show the score as goals scored
User prompt
ball moves 100% faster
User prompt
ball goes back when it hits the keeper
User prompt
when ball hits the keeper it is reflected
User prompt
put a goal keeper infront of the keep that moves horizontally ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
wind affects ball direction
User prompt
ball spins when moving ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
remove goal post
User prompt
when ball enters goal post it is a score
User prompt
goal scored when ball enters the post from below
User prompt
double tap passes to next shoot
User prompt
goal only if ball enters from below the post
User prompt
ball moves more rapidly
User prompt
pass to next shot after ball stops moving
User prompt
go to next shot when ball stops
User prompt
no gravity
User prompt
arrange the force to shoot by holding mouse button
User prompt
shoot by pressing the point you want to shoot
Code edit (1 edits merged)
Please save this source code
User prompt
Flick Goal Master
User prompt
football
Initial prompt
hello
/**** * 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.5; self.isFlying = false; self.startX = 0; self.startY = 0; self.reset = function () { self.x = 1024; self.y = 2500; self.velocityX = 0; self.velocityY = 0; self.isFlying = false; self.startX = self.x; self.startY = self.y; self.lastY = self.y; }; self.flick = function (targetX, targetY, power) { var deltaX = targetX - self.x; var deltaY = targetY - self.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); self.velocityX = deltaX / distance * power * 0.1; self.velocityY = deltaY / distance * power * 0.1; // Apply wind effect self.velocityX += windStrength * 0.01; self.isFlying = true; LK.getSound('kick').play(); }; self.update = function () { if (self.isFlying) { self.lastY = self.y; self.x += self.velocityX; self.y += self.velocityY; // Calculate rotation based on velocity for spinning effect var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY); ballGraphics.rotation += speed * 0.02; // Apply air resistance self.velocityX *= 0.998; self.velocityY *= 0.998; // Ground collision if (self.y >= 2500) { self.y = 2500; self.velocityY = -self.velocityY * 0.6; self.velocityX *= 0.8; if (Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 1) { self.isFlying = false; } } // Side boundaries if (self.x <= 30 || self.x >= 2018) { self.velocityX = -self.velocityX * 0.7; self.x = Math.max(30, Math.min(2018, self.x)); } // Top boundary if (self.y <= 30) { self.y = 30; self.velocityY = Math.abs(self.velocityY); } } }; return self; }); var Goal = Container.expand(function () { var self = Container.call(this); var crossbar = self.attachAsset('crossbar', { anchorX: 0.5, anchorY: 0.5 }); self.goalWidth = 200; self.goalHeight = 200; self.setup = function (x, y) { self.x = x; self.y = y; crossbar.x = 0; crossbar.y = -self.goalHeight; }; self.checkGoal = function (ballX, ballY, ballLastY) { var leftPostX = self.x - self.goalWidth / 2; var rightPostX = self.x + self.goalWidth / 2; var crossbarY = self.y - self.goalHeight; // Check if ball is within goal area horizontally var inGoalAreaHorizontally = ballX > leftPostX && ballX < rightPostX; // Check if ball is currently above crossbar (inside goal vertically) var aboveCrossbar = ballY < crossbarY; // Check if ball entered from below the crossbar (was below crossbar and now above it) var enteredFromBelow = ballLastY >= crossbarY && ballY < crossbarY; return inGoalAreaHorizontally && aboveCrossbar && enteredFromBelow; }; return self; }); var Goalkeeper = Container.expand(function () { var self = Container.call(this); var keeperGraphics = self.attachAsset('goalkeeper', { anchorX: 0.5, anchorY: 1.0 }); self.moveSpeed = 2; self.direction = 1; self.goalX = 0; self.goalWidth = 200; self.setup = function (goalX, goalWidth) { self.goalX = goalX; self.goalWidth = goalWidth; self.x = goalX; self.y = 800; // Position at ground level in front of goal }; self.update = function () { // Move horizontally within goal area self.x += self.moveSpeed * self.direction; // Bounce between goal posts var leftBound = self.goalX - self.goalWidth / 2; var rightBound = self.goalX + self.goalWidth / 2; if (self.x <= leftBound || self.x >= rightBound) { self.direction *= -1; // Use tween for smooth direction change tween(self, { scaleX: self.direction }, { duration: 200, easing: tween.easeOut }); } }; return self; }); var WindIndicator = Container.expand(function () { var self = Container.call(this); var arrow = self.attachAsset('windArrow', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { arrow.rotation = windDirection; arrow.scaleX = Math.abs(windStrength) * 0.5 + 0.5; arrow.alpha = Math.abs(windStrength) * 0.3 + 0.7; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x4a90e2 }); /**** * Game Code ****/ var ball = new Ball(); var goal = new Goal(); var goalkeeper = new Goalkeeper(); var windIndicator = new WindIndicator(); // Game state variables var gameState = 'aiming'; // 'aiming', 'flying', 'resetting' var shots = 0; var maxShots = 10; var windStrength = 0; var windDirection = 0; var difficulty = 1; var goalMoveSpeed = 0; var goalDirection = 1; // Hold-to-power variables var isHolding = false; var holdStartTime = 0; var holdTargetX = 0; var holdTargetY = 0; var maxHoldTime = 2000; // 2 seconds for maximum power // Double tap variables var lastTapTime = 0; var doubleTapDelay = 300; // 300ms window for double tap // Initialize ground var ground = game.attachAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: 2632 }); // Initialize game objects ball.reset(); goal.setup(1024, 800); goalkeeper.setup(1024, 200); windIndicator.x = 200; windIndicator.y = 200; game.addChild(ball); game.addChild(goal); game.addChild(goalkeeper); game.addChild(windIndicator); // Goals display var goalsScoredCount = 0; var scoreTxt = new Text2('Goals: 0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Shots remaining display var shotsTxt = new Text2('Shots: 10', { size: 60, fill: 0xFFFFFF }); shotsTxt.anchor.set(1, 0); shotsTxt.x = -50; shotsTxt.y = 100; LK.gui.topRight.addChild(shotsTxt); // Wind display var windTxt = new Text2('Wind: None', { size: 50, fill: 0xFFFFFF }); windTxt.anchor.set(0, 0); windTxt.x = 50; windTxt.y = 100; LK.gui.topLeft.addChild(windTxt); // Power display var powerTxt = new Text2('Power: 0%', { size: 60, fill: 0xFFFF00 }); powerTxt.anchor.set(0.5, 0); powerTxt.x = 0; powerTxt.y = 150; LK.gui.top.addChild(powerTxt); function updateWind() { windDirection = (Math.random() - 0.5) * Math.PI; windStrength = (Math.random() - 0.5) * 2; var windText = 'Wind: '; if (Math.abs(windStrength) < 0.3) { windText += 'Light'; } else if (Math.abs(windStrength) < 0.7) { windText += 'Moderate'; } else { windText += 'Strong'; } if (windStrength > 0) { windText += ' →'; } else { windText += ' ←'; } windTxt.setText(windText); } function resetRound() { ball.reset(); gameState = 'aiming'; shots++; // Update shots display shotsTxt.setText('Shots: ' + (maxShots - shots)); // Check game over if (shots >= maxShots) { LK.showGameOver(); return; } // Increase difficulty difficulty = Math.floor(shots / 3) + 1; goalMoveSpeed = Math.min(difficulty * 0.5, 3); // Update wind updateWind(); // Move goal to new position var newGoalX = 500 + Math.random() * 1048; var newGoalY = 300 + Math.random() * 500; goal.setup(newGoalX, newGoalY); goalkeeper.setup(newGoalX, goal.goalWidth); } function calculatePower(startX, startY, endX, endY) { var deltaX = endX - startX; var deltaY = endY - startY; return Math.sqrt(deltaX * deltaX + deltaY * deltaY); } // Initialize first round updateWind(); game.down = function (x, y, obj) { var currentTime = Date.now(); // Check for double tap if (currentTime - lastTapTime < doubleTapDelay) { // Double tap detected - skip to next shot if (gameState === 'flying' || gameState === 'aiming') { resetRound(); return; } } lastTapTime = currentTime; if (gameState === 'aiming' && !ball.isFlying) { // Start holding for power calculation isHolding = true; holdStartTime = Date.now(); holdTargetX = x; holdTargetY = y; } }; game.up = function (x, y, obj) { if (gameState === 'aiming' && !ball.isFlying && isHolding) { // Calculate hold time and convert to power var holdTime = Date.now() - holdStartTime; var power = Math.min(holdTime / maxHoldTime * 400, 400); // Scale to max 400 power power = Math.max(power, 50); // Ensure minimum power // Shoot toward the target point ball.flick(holdTargetX, holdTargetY, power); gameState = 'flying'; isHolding = false; } }; game.update = function () { // Update wind indicator windIndicator.update(); // Update goalkeeper movement goalkeeper.update(); // Update power display during hold if (isHolding) { var holdTime = Date.now() - holdStartTime; var powerPercent = Math.min(holdTime / maxHoldTime * 100, 100); powerTxt.setText('Power: ' + Math.floor(powerPercent) + '%'); powerTxt.visible = true; } else { powerTxt.visible = false; } // Move goal based on difficulty if (difficulty > 2) { goal.x += goalMoveSpeed * goalDirection; if (goal.x <= 300 || goal.x >= 1748) { goalDirection *= -1; } } // Check for collision with goalkeeper if (ball.isFlying && ball.intersects(goalkeeper)) { // Calculate reflection angle based on where ball hits goalkeeper var relativeHitX = ball.x - goalkeeper.x; var reflectionAngle = relativeHitX * 0.02; // Increased reflection sensitivity // Reflect velocity with energy loss - ensure ball goes back towards player ball.velocityX = -Math.abs(ball.velocityX) * 0.9 + reflectionAngle; // Force negative X (back towards player) ball.velocityY = -Math.abs(ball.velocityY) * 0.8; // Always bounce upward with more energy // Add goalkeeper movement influence ball.velocityX += goalkeeper.direction * goalkeeper.moveSpeed * 0.5; // Add some spin effect tween(ball, { rotation: ball.rotation + Math.PI * 2 }, { duration: 500, easing: tween.easeOut }); // Move ball away from goalkeeper to prevent multiple collisions ball.x = goalkeeper.x - 60; // Position ball in front of goalkeeper ball.y -= 10; // Lift ball slightly } // Check for goal if (ball.isFlying && goal.checkGoal(ball.x, ball.y, ball.lastY)) { goalsScoredCount++; scoreTxt.setText('Goals: ' + goalsScoredCount); LK.getSound('goal').play(); LK.effects.flashScreen(0x00ff00, 500); resetRound(); } // Check if ball has stopped and missed if (gameState === 'flying' && !ball.isFlying) { resetRound(); } // Victory condition if (goalsScoredCount >= 5) { LK.showYouWin(); } };
/****
* 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.5;
self.isFlying = false;
self.startX = 0;
self.startY = 0;
self.reset = function () {
self.x = 1024;
self.y = 2500;
self.velocityX = 0;
self.velocityY = 0;
self.isFlying = false;
self.startX = self.x;
self.startY = self.y;
self.lastY = self.y;
};
self.flick = function (targetX, targetY, power) {
var deltaX = targetX - self.x;
var deltaY = targetY - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
self.velocityX = deltaX / distance * power * 0.1;
self.velocityY = deltaY / distance * power * 0.1;
// Apply wind effect
self.velocityX += windStrength * 0.01;
self.isFlying = true;
LK.getSound('kick').play();
};
self.update = function () {
if (self.isFlying) {
self.lastY = self.y;
self.x += self.velocityX;
self.y += self.velocityY;
// Calculate rotation based on velocity for spinning effect
var speed = Math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY);
ballGraphics.rotation += speed * 0.02;
// Apply air resistance
self.velocityX *= 0.998;
self.velocityY *= 0.998;
// Ground collision
if (self.y >= 2500) {
self.y = 2500;
self.velocityY = -self.velocityY * 0.6;
self.velocityX *= 0.8;
if (Math.abs(self.velocityY) < 2 && Math.abs(self.velocityX) < 1) {
self.isFlying = false;
}
}
// Side boundaries
if (self.x <= 30 || self.x >= 2018) {
self.velocityX = -self.velocityX * 0.7;
self.x = Math.max(30, Math.min(2018, self.x));
}
// Top boundary
if (self.y <= 30) {
self.y = 30;
self.velocityY = Math.abs(self.velocityY);
}
}
};
return self;
});
var Goal = Container.expand(function () {
var self = Container.call(this);
var crossbar = self.attachAsset('crossbar', {
anchorX: 0.5,
anchorY: 0.5
});
self.goalWidth = 200;
self.goalHeight = 200;
self.setup = function (x, y) {
self.x = x;
self.y = y;
crossbar.x = 0;
crossbar.y = -self.goalHeight;
};
self.checkGoal = function (ballX, ballY, ballLastY) {
var leftPostX = self.x - self.goalWidth / 2;
var rightPostX = self.x + self.goalWidth / 2;
var crossbarY = self.y - self.goalHeight;
// Check if ball is within goal area horizontally
var inGoalAreaHorizontally = ballX > leftPostX && ballX < rightPostX;
// Check if ball is currently above crossbar (inside goal vertically)
var aboveCrossbar = ballY < crossbarY;
// Check if ball entered from below the crossbar (was below crossbar and now above it)
var enteredFromBelow = ballLastY >= crossbarY && ballY < crossbarY;
return inGoalAreaHorizontally && aboveCrossbar && enteredFromBelow;
};
return self;
});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 1.0
});
self.moveSpeed = 2;
self.direction = 1;
self.goalX = 0;
self.goalWidth = 200;
self.setup = function (goalX, goalWidth) {
self.goalX = goalX;
self.goalWidth = goalWidth;
self.x = goalX;
self.y = 800; // Position at ground level in front of goal
};
self.update = function () {
// Move horizontally within goal area
self.x += self.moveSpeed * self.direction;
// Bounce between goal posts
var leftBound = self.goalX - self.goalWidth / 2;
var rightBound = self.goalX + self.goalWidth / 2;
if (self.x <= leftBound || self.x >= rightBound) {
self.direction *= -1;
// Use tween for smooth direction change
tween(self, {
scaleX: self.direction
}, {
duration: 200,
easing: tween.easeOut
});
}
};
return self;
});
var WindIndicator = Container.expand(function () {
var self = Container.call(this);
var arrow = self.attachAsset('windArrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
arrow.rotation = windDirection;
arrow.scaleX = Math.abs(windStrength) * 0.5 + 0.5;
arrow.alpha = Math.abs(windStrength) * 0.3 + 0.7;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x4a90e2
});
/****
* Game Code
****/
var ball = new Ball();
var goal = new Goal();
var goalkeeper = new Goalkeeper();
var windIndicator = new WindIndicator();
// Game state variables
var gameState = 'aiming'; // 'aiming', 'flying', 'resetting'
var shots = 0;
var maxShots = 10;
var windStrength = 0;
var windDirection = 0;
var difficulty = 1;
var goalMoveSpeed = 0;
var goalDirection = 1;
// Hold-to-power variables
var isHolding = false;
var holdStartTime = 0;
var holdTargetX = 0;
var holdTargetY = 0;
var maxHoldTime = 2000; // 2 seconds for maximum power
// Double tap variables
var lastTapTime = 0;
var doubleTapDelay = 300; // 300ms window for double tap
// Initialize ground
var ground = game.attachAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2632
});
// Initialize game objects
ball.reset();
goal.setup(1024, 800);
goalkeeper.setup(1024, 200);
windIndicator.x = 200;
windIndicator.y = 200;
game.addChild(ball);
game.addChild(goal);
game.addChild(goalkeeper);
game.addChild(windIndicator);
// Goals display
var goalsScoredCount = 0;
var scoreTxt = new Text2('Goals: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Shots remaining display
var shotsTxt = new Text2('Shots: 10', {
size: 60,
fill: 0xFFFFFF
});
shotsTxt.anchor.set(1, 0);
shotsTxt.x = -50;
shotsTxt.y = 100;
LK.gui.topRight.addChild(shotsTxt);
// Wind display
var windTxt = new Text2('Wind: None', {
size: 50,
fill: 0xFFFFFF
});
windTxt.anchor.set(0, 0);
windTxt.x = 50;
windTxt.y = 100;
LK.gui.topLeft.addChild(windTxt);
// Power display
var powerTxt = new Text2('Power: 0%', {
size: 60,
fill: 0xFFFF00
});
powerTxt.anchor.set(0.5, 0);
powerTxt.x = 0;
powerTxt.y = 150;
LK.gui.top.addChild(powerTxt);
function updateWind() {
windDirection = (Math.random() - 0.5) * Math.PI;
windStrength = (Math.random() - 0.5) * 2;
var windText = 'Wind: ';
if (Math.abs(windStrength) < 0.3) {
windText += 'Light';
} else if (Math.abs(windStrength) < 0.7) {
windText += 'Moderate';
} else {
windText += 'Strong';
}
if (windStrength > 0) {
windText += ' →';
} else {
windText += ' ←';
}
windTxt.setText(windText);
}
function resetRound() {
ball.reset();
gameState = 'aiming';
shots++;
// Update shots display
shotsTxt.setText('Shots: ' + (maxShots - shots));
// Check game over
if (shots >= maxShots) {
LK.showGameOver();
return;
}
// Increase difficulty
difficulty = Math.floor(shots / 3) + 1;
goalMoveSpeed = Math.min(difficulty * 0.5, 3);
// Update wind
updateWind();
// Move goal to new position
var newGoalX = 500 + Math.random() * 1048;
var newGoalY = 300 + Math.random() * 500;
goal.setup(newGoalX, newGoalY);
goalkeeper.setup(newGoalX, goal.goalWidth);
}
function calculatePower(startX, startY, endX, endY) {
var deltaX = endX - startX;
var deltaY = endY - startY;
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
}
// Initialize first round
updateWind();
game.down = function (x, y, obj) {
var currentTime = Date.now();
// Check for double tap
if (currentTime - lastTapTime < doubleTapDelay) {
// Double tap detected - skip to next shot
if (gameState === 'flying' || gameState === 'aiming') {
resetRound();
return;
}
}
lastTapTime = currentTime;
if (gameState === 'aiming' && !ball.isFlying) {
// Start holding for power calculation
isHolding = true;
holdStartTime = Date.now();
holdTargetX = x;
holdTargetY = y;
}
};
game.up = function (x, y, obj) {
if (gameState === 'aiming' && !ball.isFlying && isHolding) {
// Calculate hold time and convert to power
var holdTime = Date.now() - holdStartTime;
var power = Math.min(holdTime / maxHoldTime * 400, 400); // Scale to max 400 power
power = Math.max(power, 50); // Ensure minimum power
// Shoot toward the target point
ball.flick(holdTargetX, holdTargetY, power);
gameState = 'flying';
isHolding = false;
}
};
game.update = function () {
// Update wind indicator
windIndicator.update();
// Update goalkeeper movement
goalkeeper.update();
// Update power display during hold
if (isHolding) {
var holdTime = Date.now() - holdStartTime;
var powerPercent = Math.min(holdTime / maxHoldTime * 100, 100);
powerTxt.setText('Power: ' + Math.floor(powerPercent) + '%');
powerTxt.visible = true;
} else {
powerTxt.visible = false;
}
// Move goal based on difficulty
if (difficulty > 2) {
goal.x += goalMoveSpeed * goalDirection;
if (goal.x <= 300 || goal.x >= 1748) {
goalDirection *= -1;
}
}
// Check for collision with goalkeeper
if (ball.isFlying && ball.intersects(goalkeeper)) {
// Calculate reflection angle based on where ball hits goalkeeper
var relativeHitX = ball.x - goalkeeper.x;
var reflectionAngle = relativeHitX * 0.02; // Increased reflection sensitivity
// Reflect velocity with energy loss - ensure ball goes back towards player
ball.velocityX = -Math.abs(ball.velocityX) * 0.9 + reflectionAngle; // Force negative X (back towards player)
ball.velocityY = -Math.abs(ball.velocityY) * 0.8; // Always bounce upward with more energy
// Add goalkeeper movement influence
ball.velocityX += goalkeeper.direction * goalkeeper.moveSpeed * 0.5;
// Add some spin effect
tween(ball, {
rotation: ball.rotation + Math.PI * 2
}, {
duration: 500,
easing: tween.easeOut
});
// Move ball away from goalkeeper to prevent multiple collisions
ball.x = goalkeeper.x - 60; // Position ball in front of goalkeeper
ball.y -= 10; // Lift ball slightly
}
// Check for goal
if (ball.isFlying && goal.checkGoal(ball.x, ball.y, ball.lastY)) {
goalsScoredCount++;
scoreTxt.setText('Goals: ' + goalsScoredCount);
LK.getSound('goal').play();
LK.effects.flashScreen(0x00ff00, 500);
resetRound();
}
// Check if ball has stopped and missed
if (gameState === 'flying' && !ball.isFlying) {
resetRound();
}
// Victory condition
if (goalsScoredCount >= 5) {
LK.showYouWin();
}
};