xxxxxxxxxx
209
let ball;
let playerPaddle;
let aiPaddle;
let playerScore = 0;
let aiScore = 0;
function setup() {
createCanvas(600, 400);
ball = new Ball();
playerPaddle = new Paddle(true);
aiPaddle = new Paddle(false);
}
function draw() {
background(0);
ball.update();
ball.show();
playerPaddle.show();
playerPaddle.update();
aiPaddle.show();
aiPaddle.update(ball);
handleCollision(playerPaddle);
handleCollision(aiPaddle);
if (ball.offScreen() === "left") {
aiScore++;
ball.reset();
} else if (ball.offScreen() === "right") {
playerScore++;
aiPaddle.improveAI(playerScore); // Improve AI difficulty
ball.reset();
}
displayScore();
// Display AI stats
displayAIStats(aiPaddle);
}
function displayScore() {
fill(255);
textSize(32);
textAlign(CENTER);
text(playerScore, width / 2 - 50, 50);
text(aiScore, width / 2 + 50, 50);
}
function handleCollision(paddle) {
if (ball.hits(paddle)) {
ball.xspeed *= -1;
let diff = ball.y - (paddle.y + paddle.h / 2);
ball.yspeed = diff * 0.3;
}
}
class Ball {
constructor() {
this.reset();
}
reset() {
this.x = width / 2;
this.y = height / 2;
this.xspeed = random(2, 4) * (random() > 0.5 ? 1 : -1);
this.yspeed = random(-3, 3);
this.r = 12;
}
update() {
this.x += this.xspeed;
this.y += this.yspeed;
if (this.y < 0 || this.y > height) {
this.yspeed *= -1;
}
}
offScreen() {
if (this.x < 0) {
return "left";
} else if (this.x > width) {
return "right";
}
return false;
}
show() {
fill(255);
ellipse(this.x, this.y, this.r * 2);
}
hits(paddle) {
if (paddle.isLeft) {
return (
this.x - this.r < paddle.x + paddle.w &&
this.y > paddle.y &&
this.y < paddle.y + paddle.h
);
} else {
return (
this.x + this.r > paddle.x &&
this.y > paddle.y &&
this.y < paddle.y + paddle.h
);
}
}
}
class Paddle {
constructor(isLeft) {
this.movementRandomness = 0.5; // Determines the extent of random movement
this.x = isLeft ? 0 : width - 20;
this.y = height / 2;
this.w = 20;
this.h = 100;
this.isLeft = isLeft;
this.reactionTime = 30; // frames to react
this.maxSpeed = 5; // maximum speed of the paddle
this.targetY = this.y;
this.waiting = true;
this.lastHit = -Infinity; // keep track of when the paddle last hit the ball
}
show() {
fill(255);
rect(this.x, this.y, this.w, this.h);
}
update(ball) {
if (this.isLeft) {
this.y = mouseY - this.h / 2;
} else {
// AI Movement
this.aiMove(ball);
}
// Paddle should not go outside the canvas
this.y = constrain(this.y, 0, height - this.h);
}
aiMove(ball) {
// React only when the ball is moving towards the paddle and crosses the midpoint
if (ball.xspeed > 0 && ball.x > width / 2) {
if (this.waiting && frameCount - this.lastHit > this.reactionTime) {
// Calculate the number of frames it will take for the ball to reach the paddle
let steps = abs((width - this.x - ball.r - ball.x) / ball.xspeed);
// Predict where the ball will be after that many frames
let predictedY = ball.y + ball.yspeed * steps;
// Handle bouncing off top and bottom
while (predictedY < 0 || predictedY > height) {
if (predictedY < 0) {
predictedY = -predictedY;
} else if (predictedY > height) {
predictedY = 2 * height - predictedY;
}
}
// Set the target Y to the predicted Y
this.targetY = predictedY;
// No longer waiting
this.waiting = false;
}
} else {
// If the ball is not moving towards the AI paddle
this.waiting = true;
}
// Reduce random movement as the ball gets closer
let distanceToBall = ball.x - this.x;
let movementFactor = map(distanceToBall, 0, width / 2, 0, this.movementRandomness);
// Add some random movement
this.targetY += random(-movementFactor, movementFactor);
// Move towards target position
this.y += constrain(this.targetY - this.y, -this.maxSpeed, this.maxSpeed);
}
// Function to make AI harder
improveAI(playerScore) {
// Decrease reaction time to a minimum threshold
const minReactionTime = 1; // Minimum reaction time
this.reactionTime = max(minReactionTime, 30 - playerScore * 2);
// Increase maximum speed to a maximum threshold
const maxSpeed = 100; // Maximum speed
this.maxSpeed = min(maxSpeed, 3 + playerScore * 0.5);
// Decrease movement randomness to a minimum threshold
const minMovementRandomness = 0.1; // Minimum randomness
this.movementRandomness = max(minMovementRandomness, 0.5 - playerScore * 0.05);
}
}
function displayAIStats(aiPaddle) {
fill(255); // Set text color to white
textSize(16); // Set text size
textAlign(CENTER, BOTTOM); // Align text to the bottom center
// Display AI Reaction Time and Max Speed
let stats = `AI Reaction Time: ${aiPaddle.reactionTime}, AI Max Speed: ${aiPaddle.maxSpeed}`;
text(stats, width / 2, height - 10); // Position text at the bottom center of the canvas
}