This topic is 1493 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

well I am making a simple pong game using dx9 and c++. I want to do the AI for the computer pong paddle. All I want the paddle to do is move up and down and up again on the edge of the screen.

##### Share on other sites

Have a Paddle object. The Paddle object can have a vertical position field (m_VerticalPos or something), which you can increase or decrease to change the Paddle's position on the screen. When you render the Paddle object, use its vertical position field to create the model transform matrix. You can use a function like D3DXMatrixTranslation to create the translation matrix (pass m_VerticalPos into the y argument).

Kinda vague, but if you want a more specific answer you'll have to ask a more specific question.

##### Share on other sites

The simplest approach is to make the paddle move up or down by having the same Y position as the ball. In the update loop you would have something like this:

cpuPaddle.y = ball.y


There is a problem here, though. The computer paddle never misses. You need do add a delay of some sort. You could add a skip frame every n-th frame so the computer paddle will miss from time to time. Another method that I like more is to add some sort of easing to the coputer paddle's movement. This will add a small delay every time the computer paddle starts moving.

cpuPaddle.y += (ball.y - cpuPaddle.y) * 0.15;

Edited by ram64

##### Share on other sites

Well, something like this in the update loop could work:

const int reactionRange = 600;

// IF the ball is near the paddle and moving towards the paddle
if ((ballY - getPosition().y <= reactionRange) && (ballDir >= 90 && ballDir <= 270))
{
// If the ball is a little to the left of the paddle, move left
if (ballX <= getPosition().x+30)
{
movement.ChangeSpeed(8);
movement.ChangeDirection(90);
}
// If the ball is a little to the right of the paddle, move right
else if (ballX >= getPosition().x + getLocalBounds().width - 30)
{
movement.ChangeDirection(270);
movement.ChangeSpeed(8);
}
// Else the ball is between the paddle ends, and there is no need to move
else movement.ChangeSpeed(0);
}


With this approach there are a few things that you can do to change the difficulty of the AI. You can change the reactionRange so that the paddle begins moving earlier. Or change the speed of the paddle. This is still extremely basic but it should serve as a base for more extensive decisions.

EDIT: Damn, I just realized that I created code for a paddle moving left to right.. But just convert it to up/down. Sorry.

Edited by PragmaOnce

##### Share on other sites

That would mean the AI player can move the paddle at an infinite speed, which I believe can make it  flawless victory for him

I think the trick is to have some limit as to what speed you can move the paddle with - so if the ball bounces of a wall and is near enough the AI player he cannot move in time to stop it. Basically, let's say for an easy game mode - the AI player would predict where the ball will be, based on it's movement vector - the ball would collide with the "goal wall" of the AI player at some y value - so the AI player would aim to get to that y value (x is fixed as you only move up and down). Basically look for the intersection point of the parametric equation for the ball movement and the wall.

Example:

Define the wall:
x=w0, for every y.
Line definition for the movement of the ball(assuming the ball is moving with constant speed):
x = x0 + bx*s
y = y0 + by*s
Direction vector for the ball b(bx,by).
Starting point of the ball B0(x0,y0).

So now you solve the equations for s:
w0 = x = x0 + bx*s
=>
s = (w0-x0)/bx (the ball should be moving on the x axis or you have a division by 0)
y = y0 + by*(w0-x0)/bx


That's how you get at what y value the ball will hit the wall of the AI player.
So each movement update the AI player should try to move towards that y with his max speed until he can reach it. Now, when will he miss? The trivial case: if the AI player's max speed is too low and the ball is too fast, so you should at least make the AI player be able to catch any ball that didn't change direction since you shot it. And here's the other thing - when will the ball change direction - when it bounces off a wall. The nearer the ball bounces of a wall to the AI player, the more likely it is that the AI player won't be able to catch it in time.
Here's an example of that case - you shoot the ball so that it will bounce off right before reaching the AI player let's say from the upper wall. So when the AI paddle reaches the upper wall it will just stay there waiting, and when the ball bounces off it won't be able to move fast enough to catch it. For higher difficulty you can give the AI player the possibility to calculate one or 2 bounces or at least approximate them to some extent, give a higher limit to the speed for the AI player paddle, nd make the ball faster(which will actually make the AI player miss more to be honest, but you will start missing more too). So by playing with that max_speed, ball_speed, the predictive possibilities for the AI, maybe even make the ball lose speed when it bounces off(basically non constant ball speed) etc. you can tweak the "difficulty level".

That example got kinda big . if anything is not clear feel free to ask. Maybe there's a better method but I can't think of such a method now(probably a method that will rather approximate things a little so the AI player would do more mistakes - kinda like a human, probably use an approximation of where the ball will be, get some randomness in the whole thing etc.).

Edited by lightxbulb

##### Share on other sites

here is my code

RECT rect;

rect.left=0;

rect.top=0;

rect.right=35;

rect.bottom=100;

RECT rect_two;

rect_two.left=989;

rect_two.top=y;

rect_two.right=1024;

rect_two.bottom=y+100;

RECT rect_three;

rect_three.left=m+506;

rect_three.top=n+380;

rect_three.right=m+516;

rect_three.bottom=n+390;

m+=5;

n+=5;

if(m>=108 && n>=278)

{

m+=5;

n-=5;

}

//draw surface to the backbuffer

d3ddev->StretchRect(surface_two, NULL, backbuffer, NULL, D3DTEXF_NONE);

//draw surface to the backbuffer

d3ddev->StretchRect(surface, NULL, backbuffer, &rect, D3DTEXF_NONE);

//draw surface to the backbuffer

d3ddev->StretchRect(surface_three, NULL, backbuffer, &rect_two, D3DTEXF_NONE);

//draw surface to the backbuffer

d3ddev->StretchRect(surface_four, NULL, backbuffer, &rect_three, D3DTEXF_NONE);

//stop rendering

d3ddev->EndScene();

d3ddev->Present(NULL, NULL, NULL, NULL);

}

?

##### Share on other sites

Do you have a question?

If not, good luck onwards.

##### Share on other sites

how do I get the ball to bounce off the edges of the screen.

##### Share on other sites

well I have tried the following code

(vel_y >= 0 && vel_y <= 664) ? vel_y+=5 : vel_y-=5;


this code moves the paddle down to the edge of the screen but I want it to move up the screen and down again.

##### Share on other sites

In pseudo-code, because I believe in learning by doing, instead of learning by copying:

Somewhere, you need to know and keep track of the position of the ball, and the speed of the ball.

if the ball is moving up, and the ball is too high up on the screen...
change/inverse the speed so the ball moves up.
if the ball is moving down, and the ball is too low on the screen...
change/inverse the speed so the ball moves up.
Move the ball according to its speed.


Similar logic applies if you want it to bounce on the left & right walls.

##### Share on other sites

You gotta check for collision with the upper and lower walls. So let's say the upper wall is at y=upperY and the lower wall is at y = lowerY.

You got some radius of the ball, so you would check for collisions kinda like this:

//ball.position.y is the y coord of your ball
{
//Collision at (ball.position.x, upperY)
//calculate the bounce-off - we want to "reflect the ball from the wall
//To calculate reflection of a vector we need the normal of the wall
// However since the wall is parallel with the Ox basis vector, the normal of the wall
//is perpendicular to it, so for the upper wall we'll have upperNormal(0,-1)
//where ball.direction is the directional vector of the ball:
kFi = dot(ball.direction,upperNormal);
ball.direction.x = ball.direction.x - 2*kFi*upperNormal.x;
ball.direction.y = ball.direction.y - 2*kFi*upperNormal.y
}

//ball.position.y is the y coord of your ball
{
//Collision at (ball.position.x, lowerY)
//calculate the bounce-off - we want to "reflect the ball from the wall
//To calculate reflection of a vector we need the normal of the wall
//However since the wall is parallel with the Ox basis vector, the normal of the wall
//is perpendicular to it, so for the lower wall we'll have lowerNormal(0,1)
//where ball.direction is the directional vector of the ball:
kFi = dot(ball.direction,lowerNormal);
ball.direction.x = ball.direction.x - 2*kFi*lowerNormal.x;
ball.direction.y = ball.direction.y - 2*kFi*lowerNormal.y
}

//And you use the new ball direction vector to move your ball once again


It's better if your ball.direction vector is normlized - then you can do this for movement:

//Each frame(if you got a game clock it's better)
ball.position = ball.position + ball.direction*ball.speed*deltaTime;
//Where you can calculate deltaTime each frame like so(not really a great way though):
deltaTime = fps*100/6;
//fps is frames per second


P.S. If something is not clear enough, tell me what it is and I'll elaborate more on it

Edited by lightxbulb

##### Share on other sites

thanks lightxbulb could you help me with the paddle movement only.

##### Share on other sites

well I can get the paddle to move up or down the screen but I cant get it to move up and down and up and down again. here is the code that moves the paddle up the screen.

RECT rect;
rect.left=0;
rect.top=vel_y+664;
rect.right=35;
rect.bottom=vel_y+764;

if (vel_y <= 0 && vel_y >= -659)
{
vel_y-=5;
}


##### Share on other sites

You can have more than 1 if in the same block of code.

You can, for example, have 1 if statement that controls moving up, and 1 if statement that controls moving down.

##### Share on other sites

You can, for example, have 1 if statement that controls moving up, and 1 if statement that controls moving down.

ok I have implemented 2 if statements but it only moves the paddle up and stays at the top of the screen.



if (vel_y <= 0 && vel_y >= -659)
{
vel_y-=5;
}

if (vel_y >= 0 && vel_y <= 659)
{
vel_y+=5;
}


##### Share on other sites

If the first if is triggered, vel_y is never above 0, and it gets decremented. This means vel_y never becomes higher than 0. This means if the first if happens, it will never swap to using the second if.

The same logic applies for the second if.

You need to re-think your if logic and try again.

I don't want to outright tell you how to solve this, because this stuff you need to be able to figure out on your own.

As a tip, try drawing the top and bottom borders on a piece of paper, and label the y coordinates. Then, using the paper, figure out when you want the paddle to move up and down.

Hint: You might have to change something to keep track of which direction the paddle is currently moving. I would suggest storing the paddle's speed and using that.

##### Share on other sites

As a tip, try drawing the top and bottom borders on a piece of paper, and label the y coordinates. Then, using the paper, figure out when you want the paddle to move up and down.

##### Share on other sites

well I can get the paddle to move up or down the screen but I cant get it to move up and down and up and down again. here is the code that moves the paddle up the screen.

RECT rect;
rect.left=0;
rect.top=vel_y+664;
rect.right=35;
rect.bottom=vel_y+764;

if (vel_y <= 0 && vel_y >= -659)
{
vel_y-=5;
}


I'll just give you the way I'd do it, and not fix your code, as CoreLactose mentioned it's more useful if you figure it out yourself(though I believe that sometimes a person needs to have seen how it works numerous times to make it work).

Here's what I would do:

1)I will give my paddle some constant speed for movement (we don't need acceleration just yet I think :) )

2)I will check when the player pressed up/down and resolve these cases

3)I will check for collisions with the walls

Incoming pseudo-code:

//At init:
int upperWallY = 10;
int lowerWallY = screenHeight-10;

//In the main loop:
//where keyPressed is a function that checks if that key was pressed
//And the other statement checks if a collision would occur
{
}

{
}


##### Share on other sites

I believe the question refers to making the AI paddle move up and down, based on the initial post.

While I would do this based on the ball's current position or something, the question seems to be related to just moving the paddle up to the ball, and then back down again.

##### Share on other sites

Lolz seems like I went full retard  I thought he was talking about his paddle.

Here's a revised version then:

1)You calculate where the ball will collide with the wall behind the AI paddle:

k = (wallBehindAIPaddleX - ballX)/ ballVelocityX; //care not to have ballVelocityX == 0
pointOfCollisionAtY = ballY + ballVelocityY*k;

2)If the y component of that point is < upperWallY or >lowerWallY the AI paddle should aim for either upperWallY+paddleSizeY/2 or lowerWallY-paddleSizeY/2, otherwise it should aim just for that point ( basically if the ball is assumed to go beyond the upper or lower wall, the paddle should just wait at the upper or lower walls, because it can't go beyond them).

Basically something like this:

//Check this once each time the ball bounces off something or the game starts
{
}

{
}

//In the main loop:
//If the distance between the paddle and the point where it wants to be can be
//taken in one go - go there
{
}
//If it can't, do it by steps each frame until you can get to where you want
else
{
}

Edited by lightxbulb

##### Share on other sites


if (vel_y <= 0 && vel_y >= -659)
{
vel_y-=5;
}

if (vel_y >= 0 && vel_y <= 659)
{
vel_y+=5;
}


Phil, walk through the code with your mind, and think about what vel_y will do under different situations.

Basically, your 2nd variables you check doesn't need to be velocity, it needs to be position.

If you can't get this, stop trying.  You gave it a good try, but this isn't the fields for you.

##### Share on other sites

thanks beer but I still like to figure things out, I am doing this just for fun.