User prompt
Add a 1vs1 mode where you face a bot, the first one to score or stop 5 goals wins ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add another mode where you have to stop goals that are increasingly difficult, unpredictable, and fast. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
After that, you have a menu with three difficulties: Easy, you only have to stop 25 slow goals, Normal, you have to stop 50 fast goals, and Hard, you have to stop 100 very fast goals.
Remix started
Copy Goalkeeper Hero
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// LK engine handles pause/play functionality automatically through built-in systems
var BotGoalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 0.0
});
keeperGraphics.tint = 0xff6666; // Red tint for bot
self.targetX = 1024;
self.reactionTime = 0;
self.maxReactionDelay = 30; // frames
self.update = function () {
// Bot AI movement with reaction delay
if (self.reactionTime > 0) {
self.reactionTime--;
return;
}
// Find closest active ball
var closestBall = null;
var closestDistance = Infinity;
for (var i = 0; i < balls.length; i++) {
if (balls[i].active && balls[i].y < 1000) {
// Only react to balls in upper half
var distance = Math.abs(balls[i].x - self.x);
if (distance < closestDistance) {
closestDistance = distance;
closestBall = balls[i];
}
}
}
if (closestBall) {
// Predict where ball will be
var predictedX = closestBall.x + closestBall.speedX * 20;
self.targetX = predictedX;
// Add some error for difficulty
self.targetX += (Math.random() - 0.5) * 200;
}
// Move toward target
var dx = self.targetX - self.x;
if (Math.abs(dx) > 5) {
self.x += dx * 0.15; // Slightly slower than player
}
// Keep within bounds
var goalLeft = 424;
var goalRight = 1624;
self.x = Math.max(goalLeft, Math.min(goalRight, self.x));
};
return self;
});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
anchorY: 1.0
});
self.targetX = 1024; // Center of goal
self.moveSpeed = 15;
self.update = function () {
// Smooth movement toward target position
var dx = self.targetX - self.x;
if (Math.abs(dx) > 5) {
self.x += dx * 0.2;
}
};
self.setTarget = function (x) {
// Keep goalkeeper within goal bounds
var goalLeft = 424;
var goalRight = 1624;
self.targetX = Math.max(goalLeft, Math.min(goalRight, x));
};
return self;
});
var SoccerBall = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('soccerBall', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = 0;
self.speedY = 0;
self.active = true;
self.update = function () {
if (!self.active) return;
self.x += self.speedX;
self.y += self.speedY;
// Add slight gravity effect
self.speedY += 0.2;
// Add curve effect if it exists
if (self.curveX) {
self.speedX += self.curveX;
}
// Add spin effect if it exists
if (self.spinSpeed) {
self.speedX += Math.sin(LK.ticks * 0.1) * self.spinSpeed;
}
// Add rotation if it exists
if (self.rotationSpeed) {
self.rotation += self.rotationSpeed;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var goalkeeper;
var balls = [];
var ballSpawnTimer = 0;
var ballSpawnInterval = 120; // 2 seconds at 60fps
var difficulty = 1;
var saves = 0;
var gameSpeed = 1;
var gameStarted = false;
var selectedDifficulty = null;
var survivalLevel = 1;
var survivalSavesForNextLevel = 10;
var difficultySettings = {
easy: {
goalTarget: 25,
ballSpeed: 1,
spawnRate: 150,
name: "Easy"
},
normal: {
goalTarget: 50,
ballSpeed: 1.5,
spawnRate: 120,
name: "Normal"
},
hard: {
goalTarget: 100,
ballSpeed: 2.5,
spawnRate: 90,
name: "Hard"
},
survival: {
goalTarget: Infinity,
ballSpeed: 1,
spawnRate: 180,
name: "Survival"
},
oneVsOne: {
goalTarget: 5,
ballSpeed: 1.5,
spawnRate: 120,
name: "1vs1"
}
};
// 1vs1 mode variables
var botGoalkeeper;
var playerScore = 0;
var botScore = 0;
var isPlayerTurn = true;
var turnTimer = 0;
var turnDuration = 300; // 5 seconds at 60fps
// Create field
var field = game.addChild(LK.getAsset('field', {
anchorX: 0,
anchorY: 1,
x: 0,
y: 2732
}));
// Create goal structure
var goalNet = game.addChild(LK.getAsset('goalNet', {
width: 1200,
anchorX: 0.5,
anchorY: 1,
x: 1024,
y: 2732
}));
goalNet.alpha = 0.3;
// Create bot goal structure (initially hidden)
var botGoalNet = game.addChild(LK.getAsset('goalNet', {
width: 1200,
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: 0
}));
botGoalNet.alpha = 0.3;
botGoalNet.visible = false;
var botLeftPost = game.addChild(LK.getAsset('goalPost', {
anchorX: 0.5,
anchorY: 0,
x: 424,
y: 0
}));
botLeftPost.visible = false;
var botRightPost = game.addChild(LK.getAsset('goalPost', {
anchorX: 0.5,
anchorY: 0,
x: 1624,
y: 0
}));
botRightPost.visible = false;
var leftPost = game.addChild(LK.getAsset('goalPost', {
anchorX: 0.5,
anchorY: 1,
x: 424,
y: 2732
}));
var rightPost = game.addChild(LK.getAsset('goalPost', {
anchorX: 0.5,
anchorY: 1,
x: 1624,
y: 2732
}));
// Create goalkeeper
goalkeeper = game.addChild(new Goalkeeper());
goalkeeper.x = 1024;
goalkeeper.y = 2732;
// Create UI
var scoreTxt = new Text2('Saves: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create difficulty selection menu
var menuContainer = new Container();
game.addChild(menuContainer);
var titleText = new Text2('Select Difficulty', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
menuContainer.addChild(titleText);
// Easy button
var easyButton = new Container();
var easyBg = LK.getAsset('goalPost', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
color: 0x00ff00
});
var easyText = new Text2('Easy - 25 Goals', {
size: 60,
fill: 0x000000
});
easyText.anchor.set(0.5, 0.5);
easyButton.addChild(easyBg);
easyButton.addChild(easyText);
easyButton.x = 1024;
easyButton.y = 1200;
menuContainer.addChild(easyButton);
// Normal button
var normalButton = new Container();
var normalBg = LK.getAsset('goalPost', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
color: 0xffff00
});
var normalText = new Text2('Normal - 50 Goals', {
size: 60,
fill: 0x000000
});
normalText.anchor.set(0.5, 0.5);
normalButton.addChild(normalBg);
normalButton.addChild(normalText);
normalButton.x = 1024;
normalButton.y = 1400;
menuContainer.addChild(normalButton);
// Hard button
var hardButton = new Container();
var hardBg = LK.getAsset('goalPost', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
color: 0xff0000
});
var hardText = new Text2('Hard - 100 Goals', {
size: 60,
fill: 0x000000
});
hardText.anchor.set(0.5, 0.5);
hardButton.addChild(hardBg);
hardButton.addChild(hardText);
hardButton.x = 1024;
hardButton.y = 1600;
menuContainer.addChild(hardButton);
// Survival button
var survivalButton = new Container();
var survivalBg = LK.getAsset('goalPost', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
color: 0x800080
});
var survivalText = new Text2('Survival Mode', {
size: 60,
fill: 0xFFFFFF
});
survivalText.anchor.set(0.5, 0.5);
survivalButton.addChild(survivalBg);
survivalButton.addChild(survivalText);
survivalButton.x = 1024;
survivalButton.y = 1800;
menuContainer.addChild(survivalButton);
// 1vs1 button
var oneVsOneButton = new Container();
var oneVsOneBg = LK.getAsset('goalPost', {
width: 400,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
color: 0x00ffff
});
var oneVsOneText = new Text2('1vs1 Mode', {
size: 60,
fill: 0x000000
});
oneVsOneText.anchor.set(0.5, 0.5);
oneVsOneButton.addChild(oneVsOneBg);
oneVsOneButton.addChild(oneVsOneText);
oneVsOneButton.x = 1024;
oneVsOneButton.y = 2000;
menuContainer.addChild(oneVsOneButton);
// Button click handlers
easyButton.down = function (x, y, obj) {
startGame('easy');
};
normalButton.down = function (x, y, obj) {
startGame('normal');
};
hardButton.down = function (x, y, obj) {
startGame('hard');
};
survivalButton.down = function (x, y, obj) {
startGame('survival');
};
oneVsOneButton.down = function (x, y, obj) {
startGame('oneVsOne');
};
// Function to start game with selected difficulty
function startGame(difficultyLevel) {
selectedDifficulty = difficultyLevel;
gameStarted = true;
menuContainer.visible = false;
var settings = difficultySettings[difficultyLevel];
gameSpeed = settings.ballSpeed;
ballSpawnInterval = settings.spawnRate;
if (difficultyLevel === '1vs1' || difficultyLevel === 'oneVsOne') {
// Initialize 1vs1 mode
selectedDifficulty = 'oneVsOne';
playerScore = 0;
botScore = 0;
isPlayerTurn = true;
turnTimer = 0;
// Show bot goal and goalkeeper
botGoalNet.visible = true;
botLeftPost.visible = true;
botRightPost.visible = true;
// Create bot goalkeeper
botGoalkeeper = game.addChild(new BotGoalkeeper());
botGoalkeeper.x = 1024;
botGoalkeeper.y = 0;
scoreTxt.setText('Player: 0 - Bot: 0 (Your Turn)');
} else if (difficultyLevel === 'survival') {
survivalLevel = 1;
survivalSavesForNextLevel = 10;
scoreTxt.setText('Saves: 0 - Level 1 (Survival)');
} else {
scoreTxt.setText('Saves: 0/' + settings.goalTarget + ' (' + settings.name + ')');
}
}
// Ball spawning function
function spawnBall() {
var ball = new SoccerBall();
if (selectedDifficulty === 'oneVsOne') {
// 1vs1 mode: balls spawn from middle and go toward current defender
ball.x = Math.random() * 800 + 624; // Center area
ball.y = 1366; // Middle of field
var targetX, targetY;
if (isPlayerTurn) {
// Ball goes toward player's goal
targetX = Math.random() * 1200 + 424;
targetY = 2732 - 100;
} else {
// Ball goes toward bot's goal
targetX = Math.random() * 1200 + 424;
targetY = 100;
}
var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
var speed = 3 * gameSpeed;
ball.speedX = (targetX - ball.x) / distance * speed;
ball.speedY = (targetY - ball.y) / distance * speed;
} else {
// Random spawn position across the field width
ball.x = Math.random() * 1600 + 224;
ball.y = 100;
if (selectedDifficulty === 'survival') {
// Survival mode: increasingly unpredictable and difficult shots
var currentSpeed = 3 + survivalLevel * 0.8;
var targetX = Math.random() * 1200 + 424;
var targetY = 2732 - 100;
var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
ball.speedX = (targetX - ball.x) / distance * currentSpeed;
ball.speedY = (targetY - ball.y) / distance * currentSpeed;
// Add curve effect for higher levels
if (survivalLevel > 3) {
ball.curveX = (Math.random() - 0.5) * 0.5;
}
// Add spin effect for even higher levels
if (survivalLevel > 6) {
ball.spinSpeed = (Math.random() - 0.5) * 0.2;
ball.rotationSpeed = Math.random() * 0.3;
}
} else {
// Normal mode behavior
var targetX = Math.random() * 1200 + 424; // Random point in goal area
var targetY = 2732 - 100; // Goal height
var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
var speed = 3 * gameSpeed;
ball.speedX = (targetX - ball.x) / distance * speed;
ball.speedY = (targetY - ball.y) / distance * speed;
}
}
balls.push(ball);
game.addChild(ball);
LK.getSound('kick').play();
}
// Touch controls
var isDragging = false;
game.down = function (x, y, obj) {
isDragging = true;
goalkeeper.setTarget(x);
};
game.move = function (x, y, obj) {
if (isDragging) {
goalkeeper.setTarget(x);
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Main game loop
game.update = function () {
// Don't run game logic until difficulty is selected
if (!gameStarted) return;
// 1vs1 mode specific logic
if (selectedDifficulty === 'oneVsOne') {
// Turn timer
turnTimer++;
if (turnTimer >= turnDuration && balls.length === 0) {
// Switch turns when no balls are active
isPlayerTurn = !isPlayerTurn;
turnTimer = 0;
var turnText = isPlayerTurn ? 'Your Turn' : 'Bot Turn';
scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (' + turnText + ')');
// Give bot goalkeeper reaction delay when it's player's turn
if (isPlayerTurn && botGoalkeeper) {
botGoalkeeper.reactionTime = botGoalkeeper.maxReactionDelay;
}
}
// Spawn balls for 1vs1
ballSpawnTimer++;
if (ballSpawnTimer >= ballSpawnInterval && balls.length === 0) {
spawnBall();
ballSpawnTimer = 0;
}
// Handle 1vs1 ball collision and scoring
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
if (!ball.active) continue;
// Check bot goal (player scores)
if (ball.y < 0 && isPlayerTurn) {
playerScore++;
LK.setScore(playerScore);
LK.getSound('goal').play();
LK.effects.flashScreen(0x00ff00, 500);
scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (Goal!)');
ball.destroy();
balls.splice(i, 1);
if (playerScore >= 5) {
LK.showYouWin();
return;
}
continue;
}
// Check player goal (bot scores)
if (ball.y > 2732 && !isPlayerTurn) {
botScore++;
LK.getSound('goal').play();
LK.effects.flashScreen(0xff0000, 500);
scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (Bot Goal!)');
ball.destroy();
balls.splice(i, 1);
if (botScore >= 5) {
LK.showGameOver();
return;
}
continue;
}
// Check saves
var savedBy = null;
if (isPlayerTurn && ball.intersects(botGoalkeeper) && ball.active && ball.y < 500) {
savedBy = 'bot';
} else if (!isPlayerTurn && ball.intersects(goalkeeper) && ball.active && ball.y > 2200) {
savedBy = 'player';
}
if (savedBy) {
ball.active = false;
var saveText = savedBy === 'player' ? 'You saved!' : 'Bot saved!';
scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (' + saveText + ')');
LK.effects.flashObject(savedBy === 'player' ? goalkeeper : botGoalkeeper, 0x00ff00, 500);
LK.getSound('save').play();
ball.destroy();
balls.splice(i, 1);
continue;
}
// Remove out of bounds balls
if (ball.y < -100 || ball.y > 2832 || ball.x < -100 || ball.x > 2148) {
ball.destroy();
balls.splice(i, 1);
continue;
}
}
return; // Skip normal mode logic for 1vs1
}
// Spawn balls
ballSpawnTimer++;
if (ballSpawnTimer >= ballSpawnInterval) {
spawnBall();
ballSpawnTimer = 0;
}
// Update and check balls
for (var i = balls.length - 1; i >= 0; i--) {
var ball = balls[i];
if (!ball.active) continue;
// Check if ball went past goal line (goal scored)
if (ball.y > 2732) {
LK.getSound('goal').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
// Check for save (collision with goalkeeper)
if (ball.intersects(goalkeeper) && ball.active) {
ball.active = false;
saves++;
LK.setScore(saves);
if (selectedDifficulty === 'survival') {
// Check for level progression in survival mode
if (saves >= survivalSavesForNextLevel) {
survivalLevel++;
survivalSavesForNextLevel += 10 + survivalLevel * 2;
// Increase difficulty - faster spawn rate and more unpredictable shots
ballSpawnInterval = Math.max(45, 180 - survivalLevel * 15);
// Visual feedback for level up
LK.effects.flashScreen(0x00ff00, 500);
tween(scoreTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(scoreTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
scoreTxt.setText('Saves: ' + saves + ' - Level ' + survivalLevel + ' (Survival)');
} else {
var settings = difficultySettings[selectedDifficulty];
scoreTxt.setText('Saves: ' + saves + '/' + settings.goalTarget + ' (' + settings.name + ')');
}
// Visual feedback for save
LK.effects.flashObject(goalkeeper, 0x00ff00, 500);
tween(goalkeeper, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(goalkeeper, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
LK.getSound('save').play();
// Remove ball
ball.destroy();
balls.splice(i, 1);
continue;
}
// Remove balls that went off screen (missed)
if (ball.y < -100 || ball.x < -100 || ball.x > 2148) {
ball.destroy();
balls.splice(i, 1);
continue;
}
// Check if ball is out of bounds horizontally (safe)
if ((ball.x < 424 || ball.x > 1624) && ball.y > 2332) {
ball.active = false;
ball.destroy();
balls.splice(i, 1);
continue;
}
}
// Win condition - based on selected difficulty (survival mode never wins, only tracks progress)
if (selectedDifficulty !== 'survival') {
var settings = difficultySettings[selectedDifficulty];
if (saves >= settings.goalTarget) {
LK.showYouWin();
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -5,8 +5,57 @@
/****
* Classes
****/
+// LK engine handles pause/play functionality automatically through built-in systems
+var BotGoalkeeper = Container.expand(function () {
+ var self = Container.call(this);
+ var keeperGraphics = self.attachAsset('goalkeeper', {
+ anchorX: 0.5,
+ anchorY: 0.0
+ });
+ keeperGraphics.tint = 0xff6666; // Red tint for bot
+ self.targetX = 1024;
+ self.reactionTime = 0;
+ self.maxReactionDelay = 30; // frames
+ self.update = function () {
+ // Bot AI movement with reaction delay
+ if (self.reactionTime > 0) {
+ self.reactionTime--;
+ return;
+ }
+ // Find closest active ball
+ var closestBall = null;
+ var closestDistance = Infinity;
+ for (var i = 0; i < balls.length; i++) {
+ if (balls[i].active && balls[i].y < 1000) {
+ // Only react to balls in upper half
+ var distance = Math.abs(balls[i].x - self.x);
+ if (distance < closestDistance) {
+ closestDistance = distance;
+ closestBall = balls[i];
+ }
+ }
+ }
+ if (closestBall) {
+ // Predict where ball will be
+ var predictedX = closestBall.x + closestBall.speedX * 20;
+ self.targetX = predictedX;
+ // Add some error for difficulty
+ self.targetX += (Math.random() - 0.5) * 200;
+ }
+ // Move toward target
+ var dx = self.targetX - self.x;
+ if (Math.abs(dx) > 5) {
+ self.x += dx * 0.15; // Slightly slower than player
+ }
+ // Keep within bounds
+ var goalLeft = 424;
+ var goalRight = 1624;
+ self.x = Math.max(goalLeft, Math.min(goalRight, self.x));
+ };
+ return self;
+});
var Goalkeeper = Container.expand(function () {
var self = Container.call(this);
var keeperGraphics = self.attachAsset('goalkeeper', {
anchorX: 0.5,
@@ -105,10 +154,23 @@
goalTarget: Infinity,
ballSpeed: 1,
spawnRate: 180,
name: "Survival"
+ },
+ oneVsOne: {
+ goalTarget: 5,
+ ballSpeed: 1.5,
+ spawnRate: 120,
+ name: "1vs1"
}
};
+// 1vs1 mode variables
+var botGoalkeeper;
+var playerScore = 0;
+var botScore = 0;
+var isPlayerTurn = true;
+var turnTimer = 0;
+var turnDuration = 300; // 5 seconds at 60fps
// Create field
var field = game.addChild(LK.getAsset('field', {
anchorX: 0,
anchorY: 1,
@@ -123,8 +185,32 @@
x: 1024,
y: 2732
}));
goalNet.alpha = 0.3;
+// Create bot goal structure (initially hidden)
+var botGoalNet = game.addChild(LK.getAsset('goalNet', {
+ width: 1200,
+ anchorX: 0.5,
+ anchorY: 0,
+ x: 1024,
+ y: 0
+}));
+botGoalNet.alpha = 0.3;
+botGoalNet.visible = false;
+var botLeftPost = game.addChild(LK.getAsset('goalPost', {
+ anchorX: 0.5,
+ anchorY: 0,
+ x: 424,
+ y: 0
+}));
+botLeftPost.visible = false;
+var botRightPost = game.addChild(LK.getAsset('goalPost', {
+ anchorX: 0.5,
+ anchorY: 0,
+ x: 1624,
+ y: 0
+}));
+botRightPost.visible = false;
var leftPost = game.addChild(LK.getAsset('goalPost', {
anchorX: 0.5,
anchorY: 1,
x: 424,
@@ -233,8 +319,27 @@
survivalButton.addChild(survivalText);
survivalButton.x = 1024;
survivalButton.y = 1800;
menuContainer.addChild(survivalButton);
+// 1vs1 button
+var oneVsOneButton = new Container();
+var oneVsOneBg = LK.getAsset('goalPost', {
+ width: 400,
+ height: 120,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ color: 0x00ffff
+});
+var oneVsOneText = new Text2('1vs1 Mode', {
+ size: 60,
+ fill: 0x000000
+});
+oneVsOneText.anchor.set(0.5, 0.5);
+oneVsOneButton.addChild(oneVsOneBg);
+oneVsOneButton.addChild(oneVsOneText);
+oneVsOneButton.x = 1024;
+oneVsOneButton.y = 2000;
+menuContainer.addChild(oneVsOneButton);
// Button click handlers
easyButton.down = function (x, y, obj) {
startGame('easy');
};
@@ -246,17 +351,36 @@
};
survivalButton.down = function (x, y, obj) {
startGame('survival');
};
+oneVsOneButton.down = function (x, y, obj) {
+ startGame('oneVsOne');
+};
// Function to start game with selected difficulty
function startGame(difficultyLevel) {
selectedDifficulty = difficultyLevel;
gameStarted = true;
menuContainer.visible = false;
var settings = difficultySettings[difficultyLevel];
gameSpeed = settings.ballSpeed;
ballSpawnInterval = settings.spawnRate;
- if (difficultyLevel === 'survival') {
+ if (difficultyLevel === '1vs1' || difficultyLevel === 'oneVsOne') {
+ // Initialize 1vs1 mode
+ selectedDifficulty = 'oneVsOne';
+ playerScore = 0;
+ botScore = 0;
+ isPlayerTurn = true;
+ turnTimer = 0;
+ // Show bot goal and goalkeeper
+ botGoalNet.visible = true;
+ botLeftPost.visible = true;
+ botRightPost.visible = true;
+ // Create bot goalkeeper
+ botGoalkeeper = game.addChild(new BotGoalkeeper());
+ botGoalkeeper.x = 1024;
+ botGoalkeeper.y = 0;
+ scoreTxt.setText('Player: 0 - Bot: 0 (Your Turn)');
+ } else if (difficultyLevel === 'survival') {
survivalLevel = 1;
survivalSavesForNextLevel = 10;
scoreTxt.setText('Saves: 0 - Level 1 (Survival)');
} else {
@@ -265,36 +389,56 @@
}
// Ball spawning function
function spawnBall() {
var ball = new SoccerBall();
- // Random spawn position across the field width
- ball.x = Math.random() * 1600 + 224;
- ball.y = 100;
- if (selectedDifficulty === 'survival') {
- // Survival mode: increasingly unpredictable and difficult shots
- var currentSpeed = 3 + survivalLevel * 0.8;
- var targetX = Math.random() * 1200 + 424;
- var targetY = 2732 - 100;
- var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
- ball.speedX = (targetX - ball.x) / distance * currentSpeed;
- ball.speedY = (targetY - ball.y) / distance * currentSpeed;
- // Add curve effect for higher levels
- if (survivalLevel > 3) {
- ball.curveX = (Math.random() - 0.5) * 0.5;
+ if (selectedDifficulty === 'oneVsOne') {
+ // 1vs1 mode: balls spawn from middle and go toward current defender
+ ball.x = Math.random() * 800 + 624; // Center area
+ ball.y = 1366; // Middle of field
+ var targetX, targetY;
+ if (isPlayerTurn) {
+ // Ball goes toward player's goal
+ targetX = Math.random() * 1200 + 424;
+ targetY = 2732 - 100;
+ } else {
+ // Ball goes toward bot's goal
+ targetX = Math.random() * 1200 + 424;
+ targetY = 100;
}
- // Add spin effect for even higher levels
- if (survivalLevel > 6) {
- ball.spinSpeed = (Math.random() - 0.5) * 0.2;
- ball.rotationSpeed = Math.random() * 0.3;
- }
- } else {
- // Normal mode behavior
- var targetX = Math.random() * 1200 + 424; // Random point in goal area
- var targetY = 2732 - 100; // Goal height
var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
var speed = 3 * gameSpeed;
ball.speedX = (targetX - ball.x) / distance * speed;
ball.speedY = (targetY - ball.y) / distance * speed;
+ } else {
+ // Random spawn position across the field width
+ ball.x = Math.random() * 1600 + 224;
+ ball.y = 100;
+ if (selectedDifficulty === 'survival') {
+ // Survival mode: increasingly unpredictable and difficult shots
+ var currentSpeed = 3 + survivalLevel * 0.8;
+ var targetX = Math.random() * 1200 + 424;
+ var targetY = 2732 - 100;
+ var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
+ ball.speedX = (targetX - ball.x) / distance * currentSpeed;
+ ball.speedY = (targetY - ball.y) / distance * currentSpeed;
+ // Add curve effect for higher levels
+ if (survivalLevel > 3) {
+ ball.curveX = (Math.random() - 0.5) * 0.5;
+ }
+ // Add spin effect for even higher levels
+ if (survivalLevel > 6) {
+ ball.spinSpeed = (Math.random() - 0.5) * 0.2;
+ ball.rotationSpeed = Math.random() * 0.3;
+ }
+ } else {
+ // Normal mode behavior
+ var targetX = Math.random() * 1200 + 424; // Random point in goal area
+ var targetY = 2732 - 100; // Goal height
+ var distance = Math.sqrt(Math.pow(targetX - ball.x, 2) + Math.pow(targetY - ball.y, 2));
+ var speed = 3 * gameSpeed;
+ ball.speedX = (targetX - ball.x) / distance * speed;
+ ball.speedY = (targetY - ball.y) / distance * speed;
+ }
}
balls.push(ball);
game.addChild(ball);
LK.getSound('kick').play();
@@ -316,8 +460,88 @@
// Main game loop
game.update = function () {
// Don't run game logic until difficulty is selected
if (!gameStarted) return;
+ // 1vs1 mode specific logic
+ if (selectedDifficulty === 'oneVsOne') {
+ // Turn timer
+ turnTimer++;
+ if (turnTimer >= turnDuration && balls.length === 0) {
+ // Switch turns when no balls are active
+ isPlayerTurn = !isPlayerTurn;
+ turnTimer = 0;
+ var turnText = isPlayerTurn ? 'Your Turn' : 'Bot Turn';
+ scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (' + turnText + ')');
+ // Give bot goalkeeper reaction delay when it's player's turn
+ if (isPlayerTurn && botGoalkeeper) {
+ botGoalkeeper.reactionTime = botGoalkeeper.maxReactionDelay;
+ }
+ }
+ // Spawn balls for 1vs1
+ ballSpawnTimer++;
+ if (ballSpawnTimer >= ballSpawnInterval && balls.length === 0) {
+ spawnBall();
+ ballSpawnTimer = 0;
+ }
+ // Handle 1vs1 ball collision and scoring
+ for (var i = balls.length - 1; i >= 0; i--) {
+ var ball = balls[i];
+ if (!ball.active) continue;
+ // Check bot goal (player scores)
+ if (ball.y < 0 && isPlayerTurn) {
+ playerScore++;
+ LK.setScore(playerScore);
+ LK.getSound('goal').play();
+ LK.effects.flashScreen(0x00ff00, 500);
+ scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (Goal!)');
+ ball.destroy();
+ balls.splice(i, 1);
+ if (playerScore >= 5) {
+ LK.showYouWin();
+ return;
+ }
+ continue;
+ }
+ // Check player goal (bot scores)
+ if (ball.y > 2732 && !isPlayerTurn) {
+ botScore++;
+ LK.getSound('goal').play();
+ LK.effects.flashScreen(0xff0000, 500);
+ scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (Bot Goal!)');
+ ball.destroy();
+ balls.splice(i, 1);
+ if (botScore >= 5) {
+ LK.showGameOver();
+ return;
+ }
+ continue;
+ }
+ // Check saves
+ var savedBy = null;
+ if (isPlayerTurn && ball.intersects(botGoalkeeper) && ball.active && ball.y < 500) {
+ savedBy = 'bot';
+ } else if (!isPlayerTurn && ball.intersects(goalkeeper) && ball.active && ball.y > 2200) {
+ savedBy = 'player';
+ }
+ if (savedBy) {
+ ball.active = false;
+ var saveText = savedBy === 'player' ? 'You saved!' : 'Bot saved!';
+ scoreTxt.setText('Player: ' + playerScore + ' - Bot: ' + botScore + ' (' + saveText + ')');
+ LK.effects.flashObject(savedBy === 'player' ? goalkeeper : botGoalkeeper, 0x00ff00, 500);
+ LK.getSound('save').play();
+ ball.destroy();
+ balls.splice(i, 1);
+ continue;
+ }
+ // Remove out of bounds balls
+ if (ball.y < -100 || ball.y > 2832 || ball.x < -100 || ball.x > 2148) {
+ ball.destroy();
+ balls.splice(i, 1);
+ continue;
+ }
+ }
+ return; // Skip normal mode logic for 1vs1
+ }
// Spawn balls
ballSpawnTimer++;
if (ballSpawnTimer >= ballSpawnInterval) {
spawnBall();
@@ -414,6 +638,5 @@
if (saves >= settings.goalTarget) {
LK.showYouWin();
}
}
-};
-// LK engine handles pause/play functionality automatically through built-in systems
\ No newline at end of file
+};
\ No newline at end of file
A common soccer ball made of leather. In-Game asset. 2d. High contrast. No shadows. Cartoon
5-year-old boy with his back turned wearing a worn t-shirt and work gloves. In-Game asset. 2d. High contrast. No shadows. Cartoon
A religious street area. In-Game asset. 2d. High contrast. No shadows
Goal net. In-Game asset. 2d. High contrast. No shadows