Legacy GM How can I make a computer AI Paddle smart enough to hit a ball in a pong game?

I am trying to make an advanced pong game where you can play another player local or against the AI.. or make the computer play against itself. So I have two paddles on the left and right side of the screen. The screen also has a lot of little walls and blocks it can bounce off of randomly placed all over the screen to make things interesting. I'm surprised I worked out the bounces of the ball to behave as you'd expect with a little randomness when it bounces off everything including the outside walls and inside obstacles.

Now is the tough part.

Right now all I have the AI paddle looking to see if the ball is within range and then moving its Y position up the the balls Y position in lower and move it down if the balls y position is higher.

But this doesn't work well at all because the AI looks like a dumb @$$! and it misses a lot of the balls. The balls takes different speeds as well based off the last color of obstacle it hit. So there is that too.

Does anyone have some code or a how to I can understand on how to make this AI paddle look smart and not like such a dumb @$$ ?? lol



When the ball is coming towards the AI, you could use the direction that the ball is moving in plus the length_dir_x/y functions to get the vector that the ball is travelling on, and then move the AI towards where it thinks the ball will be based on that.


Right now all I have the AI paddle looking to see if the ball is within range and then moving its Y position up the the balls Y position in lower and move it down if the balls position is higher.
What do you mean by "in range?" And, do the balls move faster than the paddles?

AI is almost always hard to do right. In fact, it's also almost always easier to make an unbeatable AI than an AI that feels human. A good way to start might be breaking the problem into pieces.

The simplest thing to do is to think about how to make an unbeatable AI- a "perfect" AI. This can be done with two guarantees:

1) balls never travel faster than paddles, and
2) paddles don't have a "range": they always mirror the ball's movement: if the ball is moving up, they move up; if the ball is moving down, they move down. As Rob suggested, you can get the y-speed of the ball so that the paddles also move up and down at the same speed as the ball.

If the paddle can always move the entirety of the y-range before the ball crosses from one side to the other, it is possible to create an AI that always hits the ball, guaranteed.

If balls travel too fast, then depending on the speed and angle of the ball, it may not be possible for the paddle to catch up.

Things get slightly more complicated when you start thinking about angles and multiple bounces, but again: if the paddle can move at the same rate as the ball, it should always be possible for it to catch the ball.

The trick comes when the paddle needs to predict where a ball will be, say, if the ball comes off an angle faster than the paddle can recover vertically. In this case, you need to predict, like a pool/billiards player, where the ball will be after each bounce. You can do this with a bit of math: using the speed of the ball horizontally and vertically to predict where it will hit the wall, what angle it will hit the wall, until, finally, it reaches the x-point where your paddle is.

Once you've made a so-called "perfect" AI like this, then comes the real challenge: making it look human. You might be able to do that by having it miscalculate the angle the the ball bounces off walls, by some margin of error.

This is obviously a very high-level overview- but it might get you started in the right direction.
Last edited:
Basic movement:
if (abs(x-ball.x) < range) {
   var ydiff = y-ball.y;
   var ysign = sign(ydiff);
   y += min(ydiff,ysign*move_speed);
Just give the paddle a range variable and a move_speed variable and store the obj_ball instance ID in the ball variable. This AI will be "perfect" in the sense that, if it CAN reach the ball with the move_speed it has, it always will.

Predictive movement:
if (abs(x-ball.x) < range) {
   var cy,cx,ty,tx,bdir,ydiff,ysign;
   bdir = ball.direction;
   cy = ball.y;
   cx = ball.x;
   ty = cy;
   tx = cx;
   while (x-tx < 0) { // This is if the paddle is on the left, change the < to a > if it's on the right
      tx += lengthdir_x(tx,bdir);
      ty += lengthdir_y(ty,bdir);
   ydiff = y-ty;
   ysign = sign(ydiff);
   y += min(ydiff,ysign*move_speed);
I haven't tested the predictive code, but it should figure out where the line of interception with the paddles x position is and move the

EDIT: Just noticed it seems like you want the paddle to predict where the ball will be. I'll edit this post in a bit to implement that.
Last edited: