Need Help with a Pong AI clone

Hello everyone, I made a small pong game a couple of months back, and I decided to revisit it. However, the AI is unbeatable, thus making the game useless. It’s because the AI can cheat in the game, where it can have any paddle velocity, whereas the player has a fixed paddle velocity. I wanted to do raycasting to show the ball’s direction, but I don’t know how. Here is the code:

class Ball {
  PVector pos;
  PVector vel;
  Ball () {
    pos = new PVector(width/2, height/2);
    vel = new PVector(-5, 0);
  }
  void show () {
    fill(255);
    ellipse(pos.x, pos.y, 30, 30);
  }
  void update () {
    pos.add(vel);
  }
  void hits (Paddle player1) {
    if (pos.x - 15 <= player1.pos.x + 20 && pos.x - 15 > 0 && pos.y - 15 >= player1.pos.y - 20 && pos.y + 15 <= player1.pos.y + 120) {
      vel = new PVector(5, floor(random(-5, 5)));
      float angle = (pos.y - player1.pos.y);
      vel.x = 6;
      vel.y = map(abs(angle), 0, 100, -6, 6);
    }
  }
  void hitting (Paddle player2) {
    if (pos.x + 15 >= player2.pos.x && pos.x + 15 < width && pos.y - 15 >= player2.pos.y - 20 && pos.y + 15 <= player2.pos.y + 120) {
      float angle = (pos.y - player2.pos.y);
      vel.x = -6;
      vel.y = map(abs(angle), 0, 120, -6, 6);
    }
  }
  void boundaries (Paddle player2) {
    pos.y = constrain(pos.y, 15, height - 15);
    if (pos.y <= 15 || pos.y >= 585) {
      vel.y *= -1;
    }
    if (pos.x <= -50) {
      pos.x = width/2;
      pos.y = height/2;
      vel = new PVector(5, floor(random(5, 2)));
      player2.pos.y = height/2 - 60;
      scoreAI++;
    } else if (pos.x >= 650) {
      pos.x = width/2;
      pos.y = height/2;
      vel = new PVector(-5, floor(random(5, 2)));
      player2.pos.y = height/2 - 60;
      scorePlayer++;
    }
  }
}
class Paddle {
  PVector pos;
  PVector vel;
  Paddle (float xPos) {
    pos = new PVector(xPos, height/2 - 50);
    vel = new PVector(0, 0);
  }
  void show (float adder) {
    fill(255);
    rect(pos.x, pos.y, 10, 100 + adder);
  }
  void move () {
    pos.add(vel);
    pos.y = constrain(pos.y, 0, height - 100);
  }
  void moveAI (Ball ball) {
    vel.mult(5);
    vel.limit(5);
    pos.y = map(ball.pos.y, 15, 585, 0, height - 100);
  }
}
int scorePlayer;
int scoreAI;
PFont font;
Paddle player1;
Paddle player2;
Ball ball;
int y = 0;
void setup () {
  frameRate(90);
  size(600, 600, P2D);
  font = createFont("font.ttf", 72);
  textFont(font);
  player1 = new Paddle(15);
  player2 = new Paddle(width - 15);
  ball = new Ball();
}
void draw () {
  background(0);
  player1.show(0);
  player1.move();
  player2.show(0);
  player2.move();
  ball.show();
  ball.update();
  ball.hits(player1);
  ball.hitting(player2);
  ball.boundaries(player2);
  player2.moveAI(ball);
  fill(255);
  stroke(255);
  textSize(72);
  textAlign(CENTER, CENTER);
  text(scorePlayer, (width/2) - 108, 72);
  text(scoreAI, (width/2) + 108, 72);
  for (int i = 0; i <= 30; i++) {
  float y = lerp(0, height + 30, i/30.0);
  line(width/2, y, width/2, y + 10);
  }
}
void keyPressed () {
  if (key == 'k') {
    player1.vel = new PVector(0, -5);  
  } else if (key == 'm') {
    player1.vel = new PVector(0, 5);  
  }
}
void keyReleased () {
  player1.vel = new PVector(0, 0);
}

Note, that I did not know about functions with return statements back then, which means that this code is nowhere near as efficient as it could be.

I think in the class when you say newVel=vel.copy() and newVel.mult(20); you can draw a line from the ball to pos.add(newVel)

AI

for the AI you can calc the dist between ball and AI paddle and add this to the AI paddle with an easing ( * 0.67 )

Chrisir