Jump to content

  • Log In with Google      Sign In   
  • Create Account

computer pong paddle


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
21 replies to this topic

#1 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 30 November 2013 - 06:51 PM

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.



Sponsor:

#2 Samith   Members   -  Reputation: 2256

Like
1Likes
Like

Posted 30 November 2013 - 07:15 PM

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.



#3 ram64   Members   -  Reputation: 860

Like
1Likes
Like

Posted 01 December 2013 - 02:14 AM

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, 01 December 2013 - 02:14 AM.


#4 PragmaOnce   Members   -  Reputation: 745

Like
0Likes
Like

Posted 01 December 2013 - 05:51 AM

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, 01 December 2013 - 05:56 AM.


#5 lightxbulb   Members   -  Reputation: 706

Like
0Likes
Like

Posted 01 December 2013 - 07:04 AM

cpuPaddle.y = ball.y

 

 

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

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 bigtongue.png . 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, 01 December 2013 - 07:32 AM.


#6 phil67rpg   Members   -  Reputation: 767

Like
-2Likes
Like

Posted 01 December 2013 - 08:04 PM

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);

}

 

 



#7 Lactose!   GDNet+   -  Reputation: 3378

Like
1Likes
Like

Posted 01 December 2013 - 08:05 PM

Do you have a question?

If not, good luck onwards.



#8 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 04 December 2013 - 10:50 PM

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



#9 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 05 December 2013 - 12:09 AM

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.



#10 Lactose!   GDNet+   -  Reputation: 3378

Like
2Likes
Like

Posted 05 December 2013 - 03:27 AM

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.



#11 lightxbulb   Members   -  Reputation: 706

Like
1Likes
Like

Posted 08 December 2013 - 02:18 AM

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
if(ball.position.y+ball.radius > upperY )
{
    //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
if(ball.position.y-ball.radius < lowerY )
{
    //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 smile.png


Edited by lightxbulb, 08 December 2013 - 04:03 AM.


#12 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 09 December 2013 - 07:53 PM

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



#13 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 18 December 2013 - 04:38 PM

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;
}


#14 Lactose!   GDNet+   -  Reputation: 3378

Like
2Likes
Like

Posted 18 December 2013 - 04:42 PM

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.



#15 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 18 December 2013 - 04:51 PM


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;
}


#16 Lactose!   GDNet+   -  Reputation: 3378

Like
2Likes
Like

Posted 18 December 2013 - 05:00 PM

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.



#17 phil67rpg   Members   -  Reputation: 767

Like
0Likes
Like

Posted 18 December 2013 - 05:30 PM


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.

I have taken your advice and will work on this problem.



#18 lightxbulb   Members   -  Reputation: 706

Like
1Likes
Like

Posted 20 December 2013 - 10:13 AM

 

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 paddleSpeed = 1;
int paddleY = screenHeight/2;//considering that is the coords for the center of your paddle
int paddleSizeY = 10;
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
If((keyPressed(KEY_UP) == true) And ((paddleY-paddleSizeY/2-paddleSpeed*deltaTime)>upperWallY ))
{
   paddleY = paddleY-paddleSpeed*deltaTime;
}

If((keyPressed(KEY_DOWN) == true) And ((paddleY+paddleSizeY/2+paddleSpeed*deltaTime)<lowerWallY ))
{
   paddleY = paddleY+paddleSpeed*deltaTime;
}


#19 Lactose!   GDNet+   -  Reputation: 3378

Like
1Likes
Like

Posted 20 December 2013 - 10:32 AM

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.



#20 lightxbulb   Members   -  Reputation: 706

Like
0Likes
Like

Posted 20 December 2013 - 11:06 AM

Lolz seems like I went full retard tongue.png 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
If(pointOfCollisionAtY-paddleSizeY/2<upperWallY)
{
   pointOfCollisionAtY = upperWallY + paddleSizeY/2;
}

If(pointOfCollisionAtY+paddleSizeY/2>upperWallY)
{
   pointOfCollisionAtY = upperWallY - paddleSizeY/2;
}

//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(abs(paddleY - pointOfCollisionAtY)<=(paddleSpeed*deltaTime))
{
    paddleY = pointOfCollisionAtY;
}
//If it can't, do it by steps each frame until you can get to where you want
else
{
    if( paddleY > pointOfCollisionAtY) paddleY = paddleY - paddleSpeed*deltaTime;
    if( paddleY < pointOfCollisionAtY) paddleY = paddleY + paddleSpeed*deltaTime;
}

Edited by lightxbulb, 20 December 2013 - 11:07 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS