User prompt
add easy medium and hard ai choises on the home screen
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'reset')' in or related to this line: 'ball.reset();' Line Number: 398
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'x')' in or related to this line: 'playerScoreText.x = table.x - 200;' Line Number: 301
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'width')' in or related to this line: 'var originalPaddleWidth = playerPaddle.width;' Line Number: 288
User prompt
add homescreen
User prompt
add powerupps
User prompt
add win and lose when ten points is reached
User prompt
ad a ping pong table
User prompt
Classic Ping Pong
Initial prompt
standard table tennis
/****
* Classes
****/
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = ballGraphics.width;
self.height = ballGraphics.height;
self.velocityX = 0;
self.velocityY = 0;
self.speed = 10;
self.maxSpeed = 20;
self.active = false;
self.lastX = 0;
self.lastY = 0;
self.isClone = false;
self.reset = function () {
self.x = table.x;
self.y = table.y;
self.velocityY = self.speed;
self.velocityX = Math.random() * 6 - 3;
self.active = true;
self.lastX = self.x;
self.lastY = self.y;
};
self.update = function () {
if (!self.active) {
return;
}
self.lastX = self.x;
self.lastY = self.y;
self.x += self.velocityX;
self.y += self.velocityY;
// Side wall collision
if (self.x < table.x - table.width / 2 + self.width / 2 || self.x > table.x + table.width / 2 - self.width / 2) {
self.velocityX = -self.velocityX;
LK.getSound('hit').play();
}
};
self.checkPaddleCollision = function (paddle) {
if (self.intersects(paddle) && (self.velocityY > 0 && self.y < paddle.y || self.velocityY < 0 && self.y > paddle.y)) {
// Calculate bounce angle based on where ball hit paddle
var hitPos = (self.x - paddle.x) / (paddle.width / 2);
self.velocityX = hitPos * 10;
// Reverse Y velocity
self.velocityY = -self.velocityY;
// Increase speed slightly
if (Math.abs(self.velocityY) < self.maxSpeed) {
self.velocityY *= 1.05;
}
LK.getSound('hit').play();
return true;
}
return false;
};
return self;
});
var HomeScreen = Container.expand(function () {
var self = Container.call(this);
self.difficulty = 'medium'; // Default difficulty
// Create title text
var titleText = new Text2("CLASSIC PING PONG", {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 3;
self.addChild(titleText);
// Create play button
var playButton = self.attachAsset('scoreboard', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
width: 400,
height: 150
});
playButton.tint = 0x4CAF50;
// Create play text
var playText = new Text2("PLAY", {
size: 80,
fill: 0xFFFFFF
});
playText.anchor.set(0.5, 0.5);
playText.x = 2048 / 2;
playText.y = 2732 / 2;
self.addChild(playText);
// Create difficulty selection buttons
var difficultyText = new Text2("SELECT DIFFICULTY:", {
size: 50,
fill: 0xFFFFFF
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.x = 2048 / 2;
difficultyText.y = 2732 / 2 + 250;
self.addChild(difficultyText);
// Create Easy Button
var easyButton = self.attachAsset('scoreboard', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 300,
y: 2732 / 2 + 350,
width: 250,
height: 100
});
easyButton.tint = 0x4CAF50; // Green
var easyText = new Text2("EASY", {
size: 40,
fill: 0xFFFFFF
});
easyText.anchor.set(0.5, 0.5);
easyText.x = 2048 / 2 - 300;
easyText.y = 2732 / 2 + 350;
self.addChild(easyText);
// Create Medium Button
var mediumButton = self.attachAsset('scoreboard', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 350,
width: 250,
height: 100
});
mediumButton.tint = 0xFFA500; // Orange
mediumButton.alpha = 1; // Selected by default
var mediumText = new Text2("MEDIUM", {
size: 40,
fill: 0xFFFFFF
});
mediumText.anchor.set(0.5, 0.5);
mediumText.x = 2048 / 2;
mediumText.y = 2732 / 2 + 350;
self.addChild(mediumText);
// Create Hard Button
var hardButton = self.attachAsset('scoreboard', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 300,
y: 2732 / 2 + 350,
width: 250,
height: 100
});
hardButton.tint = 0xFF0000; // Red
var hardText = new Text2("HARD", {
size: 40,
fill: 0xFFFFFF
});
hardText.anchor.set(0.5, 0.5);
hardText.x = 2048 / 2 + 300;
hardText.y = 2732 / 2 + 350;
self.addChild(hardText);
// Create instructions text
var instructionsText = new Text2("First to score 10 points wins!\nDrag to move your paddle", {
size: 50,
fill: 0xFFFFFF
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 2048 / 2;
instructionsText.y = 2732 / 2 + 450;
self.addChild(instructionsText);
// Function to update button appearance
function updateDifficultyButtons() {
easyButton.alpha = self.difficulty === 'easy' ? 1 : 0.7;
mediumButton.alpha = self.difficulty === 'medium' ? 1 : 0.7;
hardButton.alpha = self.difficulty === 'hard' ? 1 : 0.7;
}
// Handle button press
self.down = function (x, y, obj) {
// Check if play button was pressed
if (x >= playButton.x - playButton.width / 2 && x <= playButton.x + playButton.width / 2 && y >= playButton.y - playButton.height / 2 && y <= playButton.y + playButton.height / 2) {
self.emit('play', self.difficulty);
}
// Check if easy button was pressed
if (x >= easyButton.x - easyButton.width / 2 && x <= easyButton.x + easyButton.width / 2 && y >= easyButton.y - easyButton.height / 2 && y <= easyButton.y + easyButton.height / 2) {
self.difficulty = 'easy';
updateDifficultyButtons();
}
// Check if medium button was pressed
if (x >= mediumButton.x - mediumButton.width / 2 && x <= mediumButton.x + mediumButton.width / 2 && y >= mediumButton.y - mediumButton.height / 2 && y <= mediumButton.y + mediumButton.height / 2) {
self.difficulty = 'medium';
updateDifficultyButtons();
}
// Check if hard button was pressed
if (x >= hardButton.x - hardButton.width / 2 && x <= hardButton.x + hardButton.width / 2 && y >= hardButton.y - hardButton.height / 2 && y <= hardButton.y + hardButton.height / 2) {
self.difficulty = 'hard';
updateDifficultyButtons();
}
};
return self;
});
// Game dimensions are 2048x2732
var Paddle = Container.expand(function () {
var self = Container.call(this);
var paddleGraphics = self.attachAsset('paddle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = paddleGraphics.width;
self.height = paddleGraphics.height;
self.speed = 10;
self.isAI = false;
self.targetX = 0;
self.update = function () {
if (self.isAI) {
// AI movement logic
if (Math.abs(self.x - self.targetX) > self.speed) {
if (self.x < self.targetX) {
self.x += self.speed;
} else {
self.x -= self.speed;
}
}
}
// Keep paddle within table bounds
if (self.x < table.x - table.width / 2 + self.width / 2 + 20) {
self.x = table.x - table.width / 2 + self.width / 2 + 20;
} else if (self.x > table.x + table.width / 2 - self.width / 2 - 20) {
self.x = table.x + table.width / 2 - self.width / 2 - 20;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = powerUpGraphics.width;
self.height = powerUpGraphics.height;
self.type = 'none';
self.active = false;
self.speed = 3;
self.activate = function (type) {
self.type = type;
self.active = true;
// Set appearance based on power-up type
switch (type) {
case 'wide':
powerUpGraphics.tint = 0x00ff00; // Green for paddle widening
break;
case 'slow':
powerUpGraphics.tint = 0x0000ff; // Blue for ball slowing
break;
case 'multi':
powerUpGraphics.tint = 0xff00ff; // Purple for multi-ball
break;
}
// Position randomly on table
self.x = table.x + (Math.random() * table.width - table.width / 2) * 0.8;
self.y = table.y + (Math.random() * table.height - table.height / 2) * 0.6;
};
self.update = function () {
if (!self.active) {
return;
}
// Slowly move downward
self.y += self.speed;
// Remove if off table
if (self.y > table.y + table.height / 2) {
self.active = false;
self.visible = false;
}
};
self.collect = function () {
self.active = false;
self.visible = false;
return self.type;
};
self.reset = function () {
self.active = false;
self.visible = false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game dimensions are 2048x2732
game.setBackgroundColor(0x1a1a1a);
// Create homescreen
var homeScreen = new HomeScreen();
game.addChild(homeScreen);
// Game state
var gameStarted = false;
var gameDifficulty = 'medium'; // Default difficulty
// Create game elements but don't start the game yet
var table, net, playerPaddle, aiPaddle, ball, balls;
// Initialize game elements
function initializeGame() {
// Create table
table = game.addChild(LK.getAsset('table', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Create net
net = game.addChild(LK.getAsset('net', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Create player paddle
playerPaddle = new Paddle();
playerPaddle.x = 2048 / 2;
playerPaddle.y = table.y + table.height / 2 - playerPaddle.height - 50;
game.addChild(playerPaddle);
// Create AI paddle
aiPaddle = new Paddle();
aiPaddle.x = 2048 / 2;
aiPaddle.y = table.y - table.height / 2 + aiPaddle.height + 50;
aiPaddle.isAI = true;
game.addChild(aiPaddle);
// Create ball
ball = new Ball();
game.addChild(ball);
// Create additional balls for multi-ball power-up
balls = [ball];
var maxBalls = 3;
for (var i = 1; i < maxBalls; i++) {
var extraBall = new Ball();
extraBall.isClone = true;
extraBall.visible = false;
extraBall.active = false;
game.addChild(extraBall);
balls.push(extraBall);
}
// Initialize power-up state variables that depend on game elements
originalPaddleWidth = playerPaddle.width;
originalBallSpeed = ball.speed;
// Position score text now that table exists
playerScoreText.x = table.x - 200;
playerScoreText.y = table.y;
aiScoreText.x = table.x + 200;
aiScoreText.y = table.y;
}
// Home screen play button event
homeScreen.on('play', function (difficulty) {
homeScreen.visible = false;
gameStarted = true;
// Set game difficulty
gameDifficulty = difficulty || 'medium';
initializeGame();
// Reset the ball now that the game is initialized
ball.reset();
});
// Create power-ups
var powerUps = [];
var maxPowerUps = 3;
for (var i = 0; i < maxPowerUps; i++) {
var powerUp = new PowerUp();
powerUp.visible = false;
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Power-up state variables
var powerUpTimer = null;
var powerUpActive = false;
var powerUpType = 'none';
var originalPaddleWidth;
var originalBallSpeed;
// Create score text
var playerScore = 0;
var aiScore = 0;
var playerScoreText = new Text2(playerScore.toString(), {
size: 80,
fill: 0xFFFFFF
});
playerScoreText.anchor.set(0.5, 0.5);
// Position will be set after table is created
game.addChild(playerScoreText);
var aiScoreText = new Text2(aiScore.toString(), {
size: 80,
fill: 0xFFFFFF
});
aiScoreText.anchor.set(0.5, 0.5);
// Position will be set after table is created
game.addChild(aiScoreText);
// Handle paddle dragging
var isDragging = false;
game.down = function (x, y, obj) {
if (gameStarted) {
isDragging = true;
playerPaddle.x = x;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
game.move = function (x, y, obj) {
if (isDragging && gameStarted) {
playerPaddle.x = x;
}
};
// Power-up activation function
function activatePowerUp(type) {
// Clear any existing power-up effect
if (powerUpTimer) {
LK.clearTimeout(powerUpTimer);
}
// Reset previous power-up effects
if (powerUpActive) {
deactivatePowerUp();
}
powerUpActive = true;
powerUpType = type;
switch (type) {
case 'wide':
// Widen paddle
playerPaddle.width = originalPaddleWidth * 1.5;
paddleGraphics = playerPaddle.children[0];
paddleGraphics.scale.x = 1.5;
break;
case 'slow':
// Slow down ball
for (var i = 0; i < balls.length; i++) {
if (balls[i].active) {
balls[i].velocityX *= 0.6;
balls[i].velocityY *= 0.6;
}
}
break;
case 'multi':
// Activate multi-ball
for (var i = 1; i < balls.length; i++) {
if (!balls[i].active) {
balls[i].x = balls[0].x;
balls[i].y = balls[0].y;
balls[i].velocityX = balls[0].velocityX * (Math.random() > 0.5 ? 1 : -1);
balls[i].velocityY = balls[0].velocityY;
balls[i].active = true;
balls[i].visible = true;
break;
}
}
break;
}
// Power-up lasts for 10 seconds
powerUpTimer = LK.setTimeout(function () {
deactivatePowerUp();
}, 10000);
}
// Function to deactivate power-ups
function deactivatePowerUp() {
powerUpActive = false;
switch (powerUpType) {
case 'wide':
playerPaddle.width = originalPaddleWidth;
paddleGraphics = playerPaddle.children[0];
paddleGraphics.scale.x = 1;
break;
case 'slow':
// Ball speed will naturally increase over time
break;
case 'multi':
// Multi-balls will remain until they go off screen
break;
}
powerUpType = 'none';
}
// Don't reset the ball until the game is started
// ball will be reset when play button is clicked
// Main game loop
game.update = function () {
// Don't update game if not started
if (!gameStarted) {
return;
}
// Update game objects
playerPaddle.update();
aiPaddle.update();
// Update all balls
for (var i = 0; i < balls.length; i++) {
if (balls[i].active) {
balls[i].update();
}
}
// Update power-ups
for (var i = 0; i < powerUps.length; i++) {
if (powerUps[i].active) {
powerUps[i].update();
// Check if player paddle collects power-up
if (powerUps[i].active && powerUps[i].intersects(playerPaddle)) {
// Apply power-up effect
var powerType = powerUps[i].collect();
activatePowerUp(powerType);
LK.getSound('powerup').play();
}
}
}
// Randomly spawn power-ups (about every 10 seconds on average)
if (Math.random() < 0.002 && !powerUpActive) {
// Find inactive power-up
for (var i = 0; i < powerUps.length; i++) {
if (!powerUps[i].active) {
var types = ['wide', 'slow', 'multi'];
var randomType = types[Math.floor(Math.random() * types.length)];
powerUps[i].activate(randomType);
powerUps[i].visible = true;
break;
}
}
}
// AI behavior - track the ball (closest one moving toward AI)
var closestBall = null;
var closestDistance = Infinity;
// Find closest ball that's moving toward AI
for (var i = 0; i < balls.length; i++) {
if (balls[i].active && balls[i].velocityY < 0) {
var distance = Math.abs(balls[i].y - aiPaddle.y);
if (distance < closestDistance) {
closestDistance = distance;
closestBall = balls[i];
}
}
}
// If no balls moving toward AI, track main ball if active
if (!closestBall && balls[0].active) {
closestBall = balls[0];
}
// Track the chosen ball
if (closestBall) {
aiPaddle.targetX = closestBall.x;
// Apply difficulty settings
var difficultySettings = {
'easy': {
reactionDelay: 0.7,
// How quickly AI reacts (higher = slower)
accuracy: 0.4,
// How accurate AI is (lower = less accurate)
maxRandomOffset: 400,
// Maximum random offset
speedFactor: 0.6 // AI paddle speed factor (lower = slower)
},
'medium': {
reactionDelay: 0.3,
accuracy: 0.7,
maxRandomOffset: 300,
speedFactor: 1.0
},
'hard': {
reactionDelay: 0.1,
accuracy: 0.9,
maxRandomOffset: 150,
speedFactor: 1.3
}
};
var settings = difficultySettings[gameDifficulty];
// Calculate AI reaction based on difficulty
if (Math.random() > settings.reactionDelay) {
// Add inaccuracy based on difficulty and ball speed
var speedFactor = Math.min(Math.abs(closestBall.velocityY) / 15, 1);
var inaccuracyFactor = (1 - settings.accuracy) * speedFactor;
var randomOffset = (Math.random() * settings.maxRandomOffset - settings.maxRandomOffset / 2) * inaccuracyFactor;
aiPaddle.targetX += randomOffset;
// Update AI paddle speed based on difficulty
aiPaddle.speed = 10 * settings.speedFactor;
}
}
// Check for collisions with all active balls
for (var i = 0; i < balls.length; i++) {
var currentBall = balls[i];
if (currentBall.active) {
currentBall.checkPaddleCollision(playerPaddle);
currentBall.checkPaddleCollision(aiPaddle);
// Check if ball goes off table (scoring)
// Player scores
if (currentBall.y < table.y - table.height / 2) {
// Only count score for non-clone balls or if it's the last active ball
if (!currentBall.isClone || countActiveBalls() == 1) {
playerScore++;
playerScoreText.setText(playerScore.toString());
LK.getSound('score').play();
// If this is the main ball, reset after short delay
if (!currentBall.isClone) {
// Deactivate all balls
for (var j = 0; j < balls.length; j++) {
balls[j].active = false;
if (j > 0) {
balls[j].visible = false;
}
}
LK.setTimeout(function () {
balls[0].reset();
}, 1000);
// Check win condition
if (playerScore === 10) {
LK.showYouWin();
}
} else {
currentBall.active = false;
currentBall.visible = false;
}
} else {
currentBall.active = false;
currentBall.visible = false;
}
}
// AI scores
if (currentBall.y > table.y + table.height / 2) {
// Only count score for non-clone balls or if it's the last active ball
if (!currentBall.isClone || countActiveBalls() == 1) {
aiScore++;
aiScoreText.setText(aiScore.toString());
LK.getSound('score').play();
// If this is the main ball, reset after short delay
if (!currentBall.isClone) {
// Deactivate all balls
for (var j = 0; j < balls.length; j++) {
balls[j].active = false;
if (j > 0) {
balls[j].visible = false;
}
}
LK.setTimeout(function () {
balls[0].reset();
}, 1000);
// Check loss condition
if (aiScore === 10) {
LK.showGameOver();
}
} else {
currentBall.active = false;
currentBall.visible = false;
}
} else {
currentBall.active = false;
currentBall.visible = false;
}
}
}
}
// Helper function to count active balls
function countActiveBalls() {
var count = 0;
for (var i = 0; i < balls.length; i++) {
if (balls[i].active) {
count++;
}
}
return count;
}
// Update score in LK system
LK.setScore(playerScore);
}; ===================================================================
--- original.js
+++ change.js
@@ -59,8 +59,9 @@
return self;
});
var HomeScreen = Container.expand(function () {
var self = Container.call(this);
+ self.difficulty = 'medium'; // Default difficulty
// Create title text
var titleText = new Text2("CLASSIC PING PONG", {
size: 100,
fill: 0xFFFFFF
@@ -87,22 +88,108 @@
playText.anchor.set(0.5, 0.5);
playText.x = 2048 / 2;
playText.y = 2732 / 2;
self.addChild(playText);
+ // Create difficulty selection buttons
+ var difficultyText = new Text2("SELECT DIFFICULTY:", {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ difficultyText.anchor.set(0.5, 0.5);
+ difficultyText.x = 2048 / 2;
+ difficultyText.y = 2732 / 2 + 250;
+ self.addChild(difficultyText);
+ // Create Easy Button
+ var easyButton = self.attachAsset('scoreboard', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2 - 300,
+ y: 2732 / 2 + 350,
+ width: 250,
+ height: 100
+ });
+ easyButton.tint = 0x4CAF50; // Green
+ var easyText = new Text2("EASY", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ easyText.anchor.set(0.5, 0.5);
+ easyText.x = 2048 / 2 - 300;
+ easyText.y = 2732 / 2 + 350;
+ self.addChild(easyText);
+ // Create Medium Button
+ var mediumButton = self.attachAsset('scoreboard', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 2732 / 2 + 350,
+ width: 250,
+ height: 100
+ });
+ mediumButton.tint = 0xFFA500; // Orange
+ mediumButton.alpha = 1; // Selected by default
+ var mediumText = new Text2("MEDIUM", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ mediumText.anchor.set(0.5, 0.5);
+ mediumText.x = 2048 / 2;
+ mediumText.y = 2732 / 2 + 350;
+ self.addChild(mediumText);
+ // Create Hard Button
+ var hardButton = self.attachAsset('scoreboard', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2 + 300,
+ y: 2732 / 2 + 350,
+ width: 250,
+ height: 100
+ });
+ hardButton.tint = 0xFF0000; // Red
+ var hardText = new Text2("HARD", {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ hardText.anchor.set(0.5, 0.5);
+ hardText.x = 2048 / 2 + 300;
+ hardText.y = 2732 / 2 + 350;
+ self.addChild(hardText);
// Create instructions text
var instructionsText = new Text2("First to score 10 points wins!\nDrag to move your paddle", {
size: 50,
fill: 0xFFFFFF
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 2048 / 2;
- instructionsText.y = 2732 / 2 + 200;
+ instructionsText.y = 2732 / 2 + 450;
self.addChild(instructionsText);
+ // Function to update button appearance
+ function updateDifficultyButtons() {
+ easyButton.alpha = self.difficulty === 'easy' ? 1 : 0.7;
+ mediumButton.alpha = self.difficulty === 'medium' ? 1 : 0.7;
+ hardButton.alpha = self.difficulty === 'hard' ? 1 : 0.7;
+ }
// Handle button press
self.down = function (x, y, obj) {
+ // Check if play button was pressed
if (x >= playButton.x - playButton.width / 2 && x <= playButton.x + playButton.width / 2 && y >= playButton.y - playButton.height / 2 && y <= playButton.y + playButton.height / 2) {
- self.emit('play');
+ self.emit('play', self.difficulty);
}
+ // Check if easy button was pressed
+ if (x >= easyButton.x - easyButton.width / 2 && x <= easyButton.x + easyButton.width / 2 && y >= easyButton.y - easyButton.height / 2 && y <= easyButton.y + easyButton.height / 2) {
+ self.difficulty = 'easy';
+ updateDifficultyButtons();
+ }
+ // Check if medium button was pressed
+ if (x >= mediumButton.x - mediumButton.width / 2 && x <= mediumButton.x + mediumButton.width / 2 && y >= mediumButton.y - mediumButton.height / 2 && y <= mediumButton.y + mediumButton.height / 2) {
+ self.difficulty = 'medium';
+ updateDifficultyButtons();
+ }
+ // Check if hard button was pressed
+ if (x >= hardButton.x - hardButton.width / 2 && x <= hardButton.x + hardButton.width / 2 && y >= hardButton.y - hardButton.height / 2 && y <= hardButton.y + hardButton.height / 2) {
+ self.difficulty = 'hard';
+ updateDifficultyButtons();
+ }
};
return self;
});
// Game dimensions are 2048x2732
@@ -207,8 +294,9 @@
var homeScreen = new HomeScreen();
game.addChild(homeScreen);
// Game state
var gameStarted = false;
+var gameDifficulty = 'medium'; // Default difficulty
// Create game elements but don't start the game yet
var table, net, playerPaddle, aiPaddle, ball, balls;
// Initialize game elements
function initializeGame() {
@@ -260,11 +348,13 @@
aiScoreText.x = table.x + 200;
aiScoreText.y = table.y;
}
// Home screen play button event
-homeScreen.on('play', function () {
+homeScreen.on('play', function (difficulty) {
homeScreen.visible = false;
gameStarted = true;
+ // Set game difficulty
+ gameDifficulty = difficulty || 'medium';
initializeGame();
// Reset the ball now that the game is initialized
ball.reset();
});
@@ -444,12 +534,43 @@
}
// Track the chosen ball
if (closestBall) {
aiPaddle.targetX = closestBall.x;
- // Add some difficulty - AI gets less accurate at higher speeds
- var difficultyFactor = Math.min(Math.abs(closestBall.velocityY) / 15, 1);
- var randomOffset = (Math.random() * 300 - 150) * difficultyFactor;
- aiPaddle.targetX += randomOffset;
+ // Apply difficulty settings
+ var difficultySettings = {
+ 'easy': {
+ reactionDelay: 0.7,
+ // How quickly AI reacts (higher = slower)
+ accuracy: 0.4,
+ // How accurate AI is (lower = less accurate)
+ maxRandomOffset: 400,
+ // Maximum random offset
+ speedFactor: 0.6 // AI paddle speed factor (lower = slower)
+ },
+ 'medium': {
+ reactionDelay: 0.3,
+ accuracy: 0.7,
+ maxRandomOffset: 300,
+ speedFactor: 1.0
+ },
+ 'hard': {
+ reactionDelay: 0.1,
+ accuracy: 0.9,
+ maxRandomOffset: 150,
+ speedFactor: 1.3
+ }
+ };
+ var settings = difficultySettings[gameDifficulty];
+ // Calculate AI reaction based on difficulty
+ if (Math.random() > settings.reactionDelay) {
+ // Add inaccuracy based on difficulty and ball speed
+ var speedFactor = Math.min(Math.abs(closestBall.velocityY) / 15, 1);
+ var inaccuracyFactor = (1 - settings.accuracy) * speedFactor;
+ var randomOffset = (Math.random() * settings.maxRandomOffset - settings.maxRandomOffset / 2) * inaccuracyFactor;
+ aiPaddle.targetX += randomOffset;
+ // Update AI paddle speed based on difficulty
+ aiPaddle.speed = 10 * settings.speedFactor;
+ }
}
// Check for collisions with all active balls
for (var i = 0; i < balls.length; i++) {
var currentBall = balls[i];