/****
* 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.reset = function () {
self.x = 2048 / 2;
self.y = 2732 / 2;
// Random angle between -45 and 45 degrees (avoiding too horizontal angles)
var angle = (Math.random() * 90 - 45) * Math.PI / 180;
// Random direction (left or right)
if (Math.random() < 0.5) {
angle = Math.PI - angle;
}
// Adjust initial speed based on difficulty
var initialSpeed = 10; // Default (medium)
if (typeof difficultySelector !== 'undefined') {
switch (difficultySelector.difficulty) {
case "easy":
initialSpeed = 8;
break;
case "medium":
initialSpeed = 10;
break;
case "hard":
initialSpeed = 12;
break;
}
}
self.velocityX = Math.cos(angle) * initialSpeed;
self.velocityY = Math.sin(angle) * initialSpeed;
self.baseSpeed = initialSpeed;
self.speedMultiplier = 1.0;
};
self.bounceFromPaddle = function (paddle, hitPosition) {
// Calculate bounce angle based on where the ball hit the paddle
// hitPosition is a normalized value from -1 (top) to 1 (bottom)
var bounceAngle = hitPosition * (Math.PI / 4); // Max 45-degree angle
// Determine direction based on which paddle was hit
var direction = self.x < 2048 / 2 ? 1 : -1;
// Get difficulty from selector and adjust speed increase
var speedIncrease = 0.05; // Default (medium)
if (difficultySelector) {
switch (difficultySelector.difficulty) {
case "easy":
speedIncrease = 0.03;
self.speedMultiplier = Math.min(self.speedMultiplier, 1.5); // Cap lower for easy
break;
case "medium":
speedIncrease = 0.05;
self.speedMultiplier = Math.min(self.speedMultiplier, 2.0); // Default cap
break;
case "hard":
speedIncrease = 0.08;
self.speedMultiplier = Math.min(self.speedMultiplier, 2.5); // Higher cap for hard
break;
}
}
// Increase speed based on difficulty
self.speedMultiplier += speedIncrease;
var speed = self.baseSpeed * self.speedMultiplier;
// Set new velocity
self.velocityX = direction * Math.cos(bounceAngle) * speed;
self.velocityY = Math.sin(bounceAngle) * speed;
// Play hit sound
LK.getSound('hit').play();
};
self.update = function () {
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off top and bottom walls
if (self.y < self.height / 2 || self.y > 2732 - self.height / 2) {
self.velocityY = -self.velocityY;
// Keep ball in bounds
self.y = Math.max(self.height / 2, Math.min(2732 - self.height / 2, self.y));
// Play hit sound
LK.getSound('hit').play();
}
};
return self;
});
var DifficultySelector = Container.expand(function () {
var self = Container.call(this);
self.difficulty = "medium"; // Default difficulty
// Create the container for the buttons
var buttonsContainer = new Container();
self.addChild(buttonsContainer);
// Create button texts
var easyButton = new Text2('EASY', {
size: 70,
fill: 0xAAAAAA
});
easyButton.anchor.set(0.5, 0.5);
easyButton.x = -250;
var mediumButton = new Text2('MEDIUM', {
size: 70,
fill: 0xFFFFFF
});
mediumButton.anchor.set(0.5, 0.5);
mediumButton.x = 0;
var hardButton = new Text2('HARD', {
size: 70,
fill: 0xAAAAAA
});
hardButton.anchor.set(0.5, 0.5);
hardButton.x = 250;
// Add buttons to container
buttonsContainer.addChild(easyButton);
buttonsContainer.addChild(mediumButton);
buttonsContainer.addChild(hardButton);
// Set interactivity
easyButton.interactive = true;
mediumButton.interactive = true;
hardButton.interactive = true;
// Event handlers
easyButton.down = function () {
self.setDifficulty("easy");
easyButton.tint = 0xFFFFFF;
mediumButton.tint = 0xAAAAAA;
hardButton.tint = 0xAAAAAA;
};
mediumButton.down = function () {
self.setDifficulty("medium");
easyButton.tint = 0xAAAAAA;
mediumButton.tint = 0xFFFFFF;
hardButton.tint = 0xAAAAAA;
};
hardButton.down = function () {
self.setDifficulty("hard");
easyButton.tint = 0xAAAAAA;
mediumButton.tint = 0xAAAAAA;
hardButton.tint = 0xFFFFFF;
};
self.setDifficulty = function (level) {
self.difficulty = level;
// Apply difficulty settings to AI paddle
if (aiPaddle) {
switch (level) {
case "easy":
aiPaddle.difficulty = 0.4;
aiPaddle.speed = 8;
break;
case "medium":
aiPaddle.difficulty = 0.7;
aiPaddle.speed = 12;
break;
case "hard":
aiPaddle.difficulty = 0.9;
aiPaddle.speed = 16;
break;
}
}
// Update winning score
if (typeof updateWinningScore === 'function') {
updateWinningScore(level);
}
// Reset the ball with new difficulty settings if game is in progress
if (ball && gameActive) {
ball.reset();
}
// Update difficulty display in bottom left if it exists
if (typeof difficultyValueText !== 'undefined') {
difficultyValueText.setText(level.toUpperCase());
}
};
return self;
});
var GameStartScreen = Container.expand(function () {
var self = Container.call(this);
// Create a transparent overlay
var overlay = new Container();
self.addChild(overlay);
// Game title
var titleText = new Text2('PONG', {
size: 150,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -250;
overlay.addChild(titleText);
// Instruction text
var instructionText = new Text2('SELECT DIFFICULTY', {
size: 70,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.y = -100;
overlay.addChild(instructionText);
// Create difficulty selector for the start screen
var startScreenSelector = null;
self.init = function () {
// Create difficulty selector
startScreenSelector = new DifficultySelector();
startScreenSelector.y = 50;
overlay.addChild(startScreenSelector);
// Start button
var startButton = new Text2('START GAME', {
size: 80,
fill: 0xFFFFFF
});
startButton.anchor.set(0.5, 0.5);
startButton.y = 200;
startButton.interactive = true;
startButton.down = function () {
self.startGame(startScreenSelector.difficulty);
};
overlay.addChild(startButton);
};
self.startGame = function (difficulty) {
// Remove start screen
self.visible = false;
// Start the actual game with selected difficulty
startGame(difficulty);
};
// Position the overlay in the center
overlay.x = 2048 / 2;
overlay.y = 2732 / 2;
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.targetY = null;
self.isAI = false;
self.difficulty = 0.7; // AI difficulty - higher is better
self.moveTowards = function (targetY) {
self.targetY = targetY;
};
self.update = function () {
if (self.targetY !== null) {
// Move towards target position
var distance = self.targetY - self.y;
var moveSpeed = Math.min(Math.abs(distance), self.speed);
if (Math.abs(distance) > 1) {
self.y += distance > 0 ? moveSpeed : -moveSpeed;
}
// Constrain paddle to screen boundaries
self.y = Math.max(self.height / 2, Math.min(2732 - self.height / 2, self.y));
}
};
self.updateAI = function (ball) {
if (!self.isAI || !ball) return;
// AI prediction logic
if (ball.velocityX > 0) {
// Ball is moving toward AI
// Predict where ball will be when it reaches AI's x position
var timeToReach = (self.x - ball.x) / ball.velocityX;
var predictedY = ball.y + ball.velocityY * timeToReach;
// Add some randomness based on difficulty
var errorAmount = (1 - self.difficulty) * 300;
var randomError = Math.random() * errorAmount - errorAmount / 2;
// Move towards predicted position with some error
self.moveTowards(predictedY + randomError);
} else {
// When ball is moving away, move towards center with some randomness
var centerY = 2732 / 2;
var randomOffset = Math.random() * 100 - 50;
self.moveTowards(centerY + randomOffset);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var WINNING_SCORE = 10; // Default for medium, will be adjusted by difficulty
// Function to update winning score based on difficulty
function updateWinningScore(difficulty) {
switch (difficulty) {
case "easy":
WINNING_SCORE = 7;
break;
case "medium":
WINNING_SCORE = 10;
break;
case "hard":
WINNING_SCORE = 15;
break;
}
}
// Game state
var playerScore = 0;
var aiScore = 0;
var lastScorer = null;
var gameActive = false;
var gameInitialized = false;
var centerLineSegments = [];
var playerPaddle, aiPaddle, ball, difficultySelector;
var playerScoreText, aiScoreText;
// Create start screen
var startScreen = new GameStartScreen();
game.addChild(startScreen);
startScreen.init();
// Initialize game elements function
function startGame(difficulty) {
gameInitialized = true;
// Setup score display if not already created
if (!playerScoreText) {
playerScoreText = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
playerScoreText.anchor.set(0.5, 0);
playerScoreText.x = GAME_WIDTH / 4;
playerScoreText.y = 50;
LK.gui.addChild(playerScoreText);
aiScoreText = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
aiScoreText.anchor.set(1, 0);
aiScoreText.x = GAME_WIDTH - 50;
aiScoreText.y = 50;
LK.gui.addChild(aiScoreText);
}
// Create center line if not already created
if (centerLineSegments.length === 0) {
var LINE_SEGMENTS = 20;
var SEGMENT_HEIGHT = GAME_HEIGHT / (LINE_SEGMENTS * 2);
for (var i = 0; i < LINE_SEGMENTS; i++) {
var segment = LK.getAsset('centerLine', {
anchorX: 0.5,
anchorY: 0.5
});
segment.y = i * SEGMENT_HEIGHT * 2 + SEGMENT_HEIGHT;
segment.x = GAME_WIDTH / 2;
game.addChild(segment);
centerLineSegments.push(segment);
}
}
// Create difficulty selector if not already created
if (!difficultySelector) {
difficultySelector = new DifficultySelector();
difficultySelector.x = GAME_WIDTH / 2;
difficultySelector.y = 150;
difficultySelector.visible = false; // Hide during gameplay
LK.gui.addChild(difficultySelector);
}
// Create paddles if not already created
if (!playerPaddle) {
playerPaddle = new Paddle();
playerPaddle.x = 80;
playerPaddle.y = GAME_HEIGHT / 2;
game.addChild(playerPaddle);
aiPaddle = new Paddle();
aiPaddle.x = GAME_WIDTH - 80;
aiPaddle.y = GAME_HEIGHT / 2;
aiPaddle.isAI = true;
game.addChild(aiPaddle);
}
// Apply selected difficulty
difficultySelector.setDifficulty(difficulty);
// Create ball if not already created
if (!ball) {
ball = new Ball();
game.addChild(ball);
}
// Reset scores at game start
playerScore = 0;
aiScore = 0;
// Reset ball to start game
ball.reset();
// Update score displays to make sure enemy score is shown
updateScoreDisplays();
// Set game as active
gameActive = true;
}
// Handle touch and mouse events
var touchActive = false;
game.down = function (x, y, obj) {
if (gameInitialized) {
touchActive = true;
playerPaddle.moveTowards(y);
}
};
game.move = function (x, y, obj) {
if (gameInitialized && touchActive) {
playerPaddle.moveTowards(y);
}
};
game.up = function (x, y, obj) {
touchActive = false;
};
// Check for paddle-ball collision
function checkPaddleCollision(paddle, ball) {
if (ball.intersects(paddle)) {
// Calculate hit position relative to paddle center (normalized from -1 to 1)
var hitPosition = (ball.y - paddle.y) / (paddle.height / 2);
hitPosition = Math.max(-1, Math.min(1, hitPosition)); // Clamp between -1 and 1
ball.bounceFromPaddle(paddle, hitPosition);
}
}
// Reset game after scoring
function resetAfterScore() {
gameActive = true;
// Reset ball with a short delay
LK.setTimeout(function () {
ball.reset();
// If AI was the last scorer, give the ball initial direction toward the player
if (lastScorer === "ai" && ball.velocityX < 0) {
ball.velocityX = -ball.velocityX;
}
// If player was the last scorer, give the ball initial direction toward the AI
else if (lastScorer === "player" && ball.velocityX > 0) {
ball.velocityX = -ball.velocityX;
}
}, 1000);
}
// Create a variable for difficulty value text that will be used by difficultySelector
var difficultyValueText;
// Update score displays
function updateScoreDisplays() {
playerScoreText.setText(playerScore.toString());
aiScoreText.setText("0");
}
// Play background music
LK.playMusic('gameBgm');
// Game update loop
game.update = function () {
if (!gameInitialized || !gameActive) return;
// Update paddles
playerPaddle.update();
aiPaddle.updateAI(ball);
// Update ball
ball.update();
// Check for paddle collisions
checkPaddleCollision(playerPaddle, ball);
checkPaddleCollision(aiPaddle, ball);
// Check for scoring
if (ball.x < 0) {
// AI scores - player loses
lastScorer = "ai";
gameActive = false;
LK.getSound('score').play();
// Show game over when ball reaches player's side
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
} else if (ball.x > GAME_WIDTH) {
// Player scores
playerScore++;
updateScoreDisplays();
lastScorer = "player";
gameActive = false;
LK.getSound('score').play();
// Check for win
if (playerScore >= WINNING_SCORE) {
LK.setScore(playerScore); // Set player's score
LK.showYouWin();
} else {
resetAfterScore();
}
}
// Update LK score (we'll use player's score)
LK.setScore(playerScore);
}; /****
* 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.reset = function () {
self.x = 2048 / 2;
self.y = 2732 / 2;
// Random angle between -45 and 45 degrees (avoiding too horizontal angles)
var angle = (Math.random() * 90 - 45) * Math.PI / 180;
// Random direction (left or right)
if (Math.random() < 0.5) {
angle = Math.PI - angle;
}
// Adjust initial speed based on difficulty
var initialSpeed = 10; // Default (medium)
if (typeof difficultySelector !== 'undefined') {
switch (difficultySelector.difficulty) {
case "easy":
initialSpeed = 8;
break;
case "medium":
initialSpeed = 10;
break;
case "hard":
initialSpeed = 12;
break;
}
}
self.velocityX = Math.cos(angle) * initialSpeed;
self.velocityY = Math.sin(angle) * initialSpeed;
self.baseSpeed = initialSpeed;
self.speedMultiplier = 1.0;
};
self.bounceFromPaddle = function (paddle, hitPosition) {
// Calculate bounce angle based on where the ball hit the paddle
// hitPosition is a normalized value from -1 (top) to 1 (bottom)
var bounceAngle = hitPosition * (Math.PI / 4); // Max 45-degree angle
// Determine direction based on which paddle was hit
var direction = self.x < 2048 / 2 ? 1 : -1;
// Get difficulty from selector and adjust speed increase
var speedIncrease = 0.05; // Default (medium)
if (difficultySelector) {
switch (difficultySelector.difficulty) {
case "easy":
speedIncrease = 0.03;
self.speedMultiplier = Math.min(self.speedMultiplier, 1.5); // Cap lower for easy
break;
case "medium":
speedIncrease = 0.05;
self.speedMultiplier = Math.min(self.speedMultiplier, 2.0); // Default cap
break;
case "hard":
speedIncrease = 0.08;
self.speedMultiplier = Math.min(self.speedMultiplier, 2.5); // Higher cap for hard
break;
}
}
// Increase speed based on difficulty
self.speedMultiplier += speedIncrease;
var speed = self.baseSpeed * self.speedMultiplier;
// Set new velocity
self.velocityX = direction * Math.cos(bounceAngle) * speed;
self.velocityY = Math.sin(bounceAngle) * speed;
// Play hit sound
LK.getSound('hit').play();
};
self.update = function () {
// Update position
self.x += self.velocityX;
self.y += self.velocityY;
// Bounce off top and bottom walls
if (self.y < self.height / 2 || self.y > 2732 - self.height / 2) {
self.velocityY = -self.velocityY;
// Keep ball in bounds
self.y = Math.max(self.height / 2, Math.min(2732 - self.height / 2, self.y));
// Play hit sound
LK.getSound('hit').play();
}
};
return self;
});
var DifficultySelector = Container.expand(function () {
var self = Container.call(this);
self.difficulty = "medium"; // Default difficulty
// Create the container for the buttons
var buttonsContainer = new Container();
self.addChild(buttonsContainer);
// Create button texts
var easyButton = new Text2('EASY', {
size: 70,
fill: 0xAAAAAA
});
easyButton.anchor.set(0.5, 0.5);
easyButton.x = -250;
var mediumButton = new Text2('MEDIUM', {
size: 70,
fill: 0xFFFFFF
});
mediumButton.anchor.set(0.5, 0.5);
mediumButton.x = 0;
var hardButton = new Text2('HARD', {
size: 70,
fill: 0xAAAAAA
});
hardButton.anchor.set(0.5, 0.5);
hardButton.x = 250;
// Add buttons to container
buttonsContainer.addChild(easyButton);
buttonsContainer.addChild(mediumButton);
buttonsContainer.addChild(hardButton);
// Set interactivity
easyButton.interactive = true;
mediumButton.interactive = true;
hardButton.interactive = true;
// Event handlers
easyButton.down = function () {
self.setDifficulty("easy");
easyButton.tint = 0xFFFFFF;
mediumButton.tint = 0xAAAAAA;
hardButton.tint = 0xAAAAAA;
};
mediumButton.down = function () {
self.setDifficulty("medium");
easyButton.tint = 0xAAAAAA;
mediumButton.tint = 0xFFFFFF;
hardButton.tint = 0xAAAAAA;
};
hardButton.down = function () {
self.setDifficulty("hard");
easyButton.tint = 0xAAAAAA;
mediumButton.tint = 0xAAAAAA;
hardButton.tint = 0xFFFFFF;
};
self.setDifficulty = function (level) {
self.difficulty = level;
// Apply difficulty settings to AI paddle
if (aiPaddle) {
switch (level) {
case "easy":
aiPaddle.difficulty = 0.4;
aiPaddle.speed = 8;
break;
case "medium":
aiPaddle.difficulty = 0.7;
aiPaddle.speed = 12;
break;
case "hard":
aiPaddle.difficulty = 0.9;
aiPaddle.speed = 16;
break;
}
}
// Update winning score
if (typeof updateWinningScore === 'function') {
updateWinningScore(level);
}
// Reset the ball with new difficulty settings if game is in progress
if (ball && gameActive) {
ball.reset();
}
// Update difficulty display in bottom left if it exists
if (typeof difficultyValueText !== 'undefined') {
difficultyValueText.setText(level.toUpperCase());
}
};
return self;
});
var GameStartScreen = Container.expand(function () {
var self = Container.call(this);
// Create a transparent overlay
var overlay = new Container();
self.addChild(overlay);
// Game title
var titleText = new Text2('PONG', {
size: 150,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -250;
overlay.addChild(titleText);
// Instruction text
var instructionText = new Text2('SELECT DIFFICULTY', {
size: 70,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.y = -100;
overlay.addChild(instructionText);
// Create difficulty selector for the start screen
var startScreenSelector = null;
self.init = function () {
// Create difficulty selector
startScreenSelector = new DifficultySelector();
startScreenSelector.y = 50;
overlay.addChild(startScreenSelector);
// Start button
var startButton = new Text2('START GAME', {
size: 80,
fill: 0xFFFFFF
});
startButton.anchor.set(0.5, 0.5);
startButton.y = 200;
startButton.interactive = true;
startButton.down = function () {
self.startGame(startScreenSelector.difficulty);
};
overlay.addChild(startButton);
};
self.startGame = function (difficulty) {
// Remove start screen
self.visible = false;
// Start the actual game with selected difficulty
startGame(difficulty);
};
// Position the overlay in the center
overlay.x = 2048 / 2;
overlay.y = 2732 / 2;
return self;
});
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.targetY = null;
self.isAI = false;
self.difficulty = 0.7; // AI difficulty - higher is better
self.moveTowards = function (targetY) {
self.targetY = targetY;
};
self.update = function () {
if (self.targetY !== null) {
// Move towards target position
var distance = self.targetY - self.y;
var moveSpeed = Math.min(Math.abs(distance), self.speed);
if (Math.abs(distance) > 1) {
self.y += distance > 0 ? moveSpeed : -moveSpeed;
}
// Constrain paddle to screen boundaries
self.y = Math.max(self.height / 2, Math.min(2732 - self.height / 2, self.y));
}
};
self.updateAI = function (ball) {
if (!self.isAI || !ball) return;
// AI prediction logic
if (ball.velocityX > 0) {
// Ball is moving toward AI
// Predict where ball will be when it reaches AI's x position
var timeToReach = (self.x - ball.x) / ball.velocityX;
var predictedY = ball.y + ball.velocityY * timeToReach;
// Add some randomness based on difficulty
var errorAmount = (1 - self.difficulty) * 300;
var randomError = Math.random() * errorAmount - errorAmount / 2;
// Move towards predicted position with some error
self.moveTowards(predictedY + randomError);
} else {
// When ball is moving away, move towards center with some randomness
var centerY = 2732 / 2;
var randomOffset = Math.random() * 100 - 50;
self.moveTowards(centerY + randomOffset);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var WINNING_SCORE = 10; // Default for medium, will be adjusted by difficulty
// Function to update winning score based on difficulty
function updateWinningScore(difficulty) {
switch (difficulty) {
case "easy":
WINNING_SCORE = 7;
break;
case "medium":
WINNING_SCORE = 10;
break;
case "hard":
WINNING_SCORE = 15;
break;
}
}
// Game state
var playerScore = 0;
var aiScore = 0;
var lastScorer = null;
var gameActive = false;
var gameInitialized = false;
var centerLineSegments = [];
var playerPaddle, aiPaddle, ball, difficultySelector;
var playerScoreText, aiScoreText;
// Create start screen
var startScreen = new GameStartScreen();
game.addChild(startScreen);
startScreen.init();
// Initialize game elements function
function startGame(difficulty) {
gameInitialized = true;
// Setup score display if not already created
if (!playerScoreText) {
playerScoreText = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
playerScoreText.anchor.set(0.5, 0);
playerScoreText.x = GAME_WIDTH / 4;
playerScoreText.y = 50;
LK.gui.addChild(playerScoreText);
aiScoreText = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
aiScoreText.anchor.set(1, 0);
aiScoreText.x = GAME_WIDTH - 50;
aiScoreText.y = 50;
LK.gui.addChild(aiScoreText);
}
// Create center line if not already created
if (centerLineSegments.length === 0) {
var LINE_SEGMENTS = 20;
var SEGMENT_HEIGHT = GAME_HEIGHT / (LINE_SEGMENTS * 2);
for (var i = 0; i < LINE_SEGMENTS; i++) {
var segment = LK.getAsset('centerLine', {
anchorX: 0.5,
anchorY: 0.5
});
segment.y = i * SEGMENT_HEIGHT * 2 + SEGMENT_HEIGHT;
segment.x = GAME_WIDTH / 2;
game.addChild(segment);
centerLineSegments.push(segment);
}
}
// Create difficulty selector if not already created
if (!difficultySelector) {
difficultySelector = new DifficultySelector();
difficultySelector.x = GAME_WIDTH / 2;
difficultySelector.y = 150;
difficultySelector.visible = false; // Hide during gameplay
LK.gui.addChild(difficultySelector);
}
// Create paddles if not already created
if (!playerPaddle) {
playerPaddle = new Paddle();
playerPaddle.x = 80;
playerPaddle.y = GAME_HEIGHT / 2;
game.addChild(playerPaddle);
aiPaddle = new Paddle();
aiPaddle.x = GAME_WIDTH - 80;
aiPaddle.y = GAME_HEIGHT / 2;
aiPaddle.isAI = true;
game.addChild(aiPaddle);
}
// Apply selected difficulty
difficultySelector.setDifficulty(difficulty);
// Create ball if not already created
if (!ball) {
ball = new Ball();
game.addChild(ball);
}
// Reset scores at game start
playerScore = 0;
aiScore = 0;
// Reset ball to start game
ball.reset();
// Update score displays to make sure enemy score is shown
updateScoreDisplays();
// Set game as active
gameActive = true;
}
// Handle touch and mouse events
var touchActive = false;
game.down = function (x, y, obj) {
if (gameInitialized) {
touchActive = true;
playerPaddle.moveTowards(y);
}
};
game.move = function (x, y, obj) {
if (gameInitialized && touchActive) {
playerPaddle.moveTowards(y);
}
};
game.up = function (x, y, obj) {
touchActive = false;
};
// Check for paddle-ball collision
function checkPaddleCollision(paddle, ball) {
if (ball.intersects(paddle)) {
// Calculate hit position relative to paddle center (normalized from -1 to 1)
var hitPosition = (ball.y - paddle.y) / (paddle.height / 2);
hitPosition = Math.max(-1, Math.min(1, hitPosition)); // Clamp between -1 and 1
ball.bounceFromPaddle(paddle, hitPosition);
}
}
// Reset game after scoring
function resetAfterScore() {
gameActive = true;
// Reset ball with a short delay
LK.setTimeout(function () {
ball.reset();
// If AI was the last scorer, give the ball initial direction toward the player
if (lastScorer === "ai" && ball.velocityX < 0) {
ball.velocityX = -ball.velocityX;
}
// If player was the last scorer, give the ball initial direction toward the AI
else if (lastScorer === "player" && ball.velocityX > 0) {
ball.velocityX = -ball.velocityX;
}
}, 1000);
}
// Create a variable for difficulty value text that will be used by difficultySelector
var difficultyValueText;
// Update score displays
function updateScoreDisplays() {
playerScoreText.setText(playerScore.toString());
aiScoreText.setText("0");
}
// Play background music
LK.playMusic('gameBgm');
// Game update loop
game.update = function () {
if (!gameInitialized || !gameActive) return;
// Update paddles
playerPaddle.update();
aiPaddle.updateAI(ball);
// Update ball
ball.update();
// Check for paddle collisions
checkPaddleCollision(playerPaddle, ball);
checkPaddleCollision(aiPaddle, ball);
// Check for scoring
if (ball.x < 0) {
// AI scores - player loses
lastScorer = "ai";
gameActive = false;
LK.getSound('score').play();
// Show game over when ball reaches player's side
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
} else if (ball.x > GAME_WIDTH) {
// Player scores
playerScore++;
updateScoreDisplays();
lastScorer = "player";
gameActive = false;
LK.getSound('score').play();
// Check for win
if (playerScore >= WINNING_SCORE) {
LK.setScore(playerScore); // Set player's score
LK.showYouWin();
} else {
resetAfterScore();
}
}
// Update LK score (we'll use player's score)
LK.setScore(playerScore);
};