Advertisement

A little help with Pong AI

Started by December 07, 2007 01:35 PM
5 comments, last by shotgunnutter 16 years, 10 months ago
I've got a pretty basic pong game going, but the AI is not working out right. for one thing the enemy paddle seems to shake up and down as it moves, sometimes it moves too fast to hit the ball. here's myu code


void MoveEnemy()
{
	// Move the enemy paddle
	Enemy_Paddle.X += Enemy_Paddle.MoveX;
	Enemy_Paddle.Y += Enemy_Paddle.MoveY;

	//Check and see if the paddle his the screen.
	if(Enemy_Paddle.Y > SCREEN_HEIGHT - Enemy_Paddle.Height)
	{
		Enemy_Paddle.Y = SCREEN_HEIGHT - Enemy_Paddle.Height;
		Enemy_Paddle.MoveY -= 20;
	}
	else if(Enemy_Paddle.Y < 0)
	{
		Enemy_Paddle.Y = 0;
		Enemy_Paddle.MoveY += 20;
	}
	 
	//Moves the Enemy Paddle based on the position of the ball
	if(Ball.X < Enemy_Paddle.X)
	{
		Enemy_Paddle.Y += Enemy_Paddle.MoveY + Ball.MoveY;
		Enemy_Paddle.MoveY *= -1;
	}
	else if(Ball.X > Enemy_Paddle.X)
	{
		Enemy_Paddle.Y += Enemy_Paddle.MoveY + Ball.MoveY;
		Enemy_Paddle.MoveY *= 1;

	} 



	if(SpriteCollision(Enemy_Paddle,Ball))
	{
		Ball.X -=  Ball.MoveX;
		Ball.MoveX *= -1;
		Ball.Y -= Ball.MoveY;
		Ball.MoveY *= -1;
		PlayWave(Enemy);
	}

}


Not sure what to do to make it work good, you might see some problems with my code, if you can give me some advice, code, ruls what ever, i'll gladly take them
Quote: Original post by Enerjak
//Moves the Enemy Paddle based on the position of the ball	if(Ball.X < Enemy_Paddle.X)	{		Enemy_Paddle.Y += Enemy_Paddle.MoveY + Ball.MoveY;		Enemy_Paddle.MoveY *= -1;	}	else if(Ball.X > Enemy_Paddle.X)	{		Enemy_Paddle.Y += Enemy_Paddle.MoveY + Ball.MoveY;		Enemy_Paddle.MoveY *= 1;	} 



I think there's something wrong here. You're checking the ball's X-position in relation to the enemy paddle's X-position, but then your responding by altering the enemy paddle's Y-position. I would rewrite this code, because you also have a line that states "Enemy_Paddle.MoveY *= 1;" which is pointless. Maybe it's just a typo. Also, why are you adding the Ball.MoveY to the enemy paddle's movement?

I think you want something like this:
//Moves the Enemy Paddle based on the position of the ball	if(Ball.X < Enemy_Paddle.X)	{		Enemy_Paddle.X -= Enemy_Paddle.MoveX;	}	else if(Ball.X > Enemy_Paddle.X)	{		Enemy_Paddle.X += Enemy_Paddle.MoveX;	} 


In this case, .MoveX represents speed, not direction. Therefore you wouldn't change the value of .MoveX unless you wanted to change the speed of the object (in this case the enemy paddle). I hope this was helpful.
Advertisement
See, what i have is this:

void MoveEnemy(){	// Move the enemy paddle	Enemy_Paddle.X += Enemy_Paddle.MoveX;	Enemy_Paddle.Y += Enemy_Paddle.MoveY;	//Check and see if the paddle his the screen.	if(Enemy_Paddle.Y > SCREEN_HEIGHT - Enemy_Paddle.Height)	{		Enemy_Paddle.Y = SCREEN_HEIGHT - Enemy_Paddle.Height;		Enemy_Paddle.MoveY -= 8;	}	else if(Enemy_Paddle.Y < 0)	{		Enemy_Paddle.Y = 0;		Enemy_Paddle.MoveY += 8;	}	 	//Moves the Enemy Paddle based on the position of the ball	if(Ball.X < Enemy_Paddle.X)	{				if(Enemy_Paddle.Y < Ball.Y)		{			Enemy_Paddle.MoveY++;		}			}	else if(Ball.X > Enemy_Paddle.X)	{		if(Enemy_Paddle.X > Ball.X)		{			Enemy_Paddle.MoveY--;		}	} 	if(SpriteCollision(Enemy_Paddle,Ball))	{		Ball.X -=  (9*rand()% Ball.MoveX);		Ball.MoveX *= -1;		Ball.Y -= (3*rand()% Ball.MoveY);		Ball.MoveY *= -1;		PlayWave(Enemy);	}}[/soruce]this is the whole function for the enemy paddle. I'm already moving the paddle then checking if it touches the edges of the screen. The AI is what's making me pissed off.
You only need to be checking one axis. If your paddles are oriented vertically like this | | then you should only be checking the Y axis. If they're oriented horizontally, the X axis.

I would also recommend giving the enemy paddle a constant velocity. This would take the form of a Vector, and you would add it to the enemy paddle's position each update.

The best (simple) way to handle the jerky paddle problem is to only change the velocity vector when the ball is completely above or below the enemy paddle. So you'll need to find the Y position of the top of the paddle and the Y position of the bottom of the paddle (again I'm assuming vertical orientation of paddles). Store these in variables in a float each update.

If the ball's Y position is less than the top paddle position, change the velocity vector to minus (paddle speed number) in the Y axis. If the ball's position is greater than the bottom paddle position, change the velocity vector to plus (paddle speed number) in the Y axis.
Quote: Original post by Enerjak
See, what i have is this:
...//Moves the Enemy Paddle based on the position of the ball	if(Ball.X < Enemy_Paddle.X)	{				if(Enemy_Paddle.Y < Ball.Y)		{			Enemy_Paddle.MoveY++;		}			}	else if(Ball.X > Enemy_Paddle.X)	{		if(Enemy_Paddle.X > Ball.X)		{			Enemy_Paddle.MoveY--;		}	} ...

this is the whole function for the enemy paddle. I'm already moving the paddle then checking if it touches the edges of the screen. The AI is what's making me pissed off.


I understand that your problem is with the AI. You need to read your code over and see what it's doing.

The second half of your code written above basically says...
If (A > B){    If (B > A)    {        (THIS CODE WILL NEVER BE TRUE!  Therefore it is pointless.)    }}


This is not the only thing wrong, but you should start here (or start this function from scratch).
Just wondering: Wouldn't it be easier to control the paddles with some "Keycode"?

So you define a variable:

char Paddle[1]; // Index: 0 = Left; 1 = Right


Then in 1P Mode you fill Paddle[0] with:
0 for no-movement if no key is pressed
1 for up-movement if P1 pressed up key
2 for down-movement if P1 pressed down key

and Paddle[1] with
0 for no-movement if the CPU would still reach the ball
1 for up-movement if the CPU is under the ball Y
2 for down-movement if the CPU is over the ball Y



Then in 2P Mode you fill Paddle[0] with
0 for no-movement if no key is pressed
1 for up-movement if P1 pressed up key
2 for down-movement if P1 pressed down key

and Paddle[1] with
0 for no-movement if no key is pressed
1 for up-movement if P2 pressed up key
2 for down-movement if P2 pressed down key


Then you add some extra parts for the paddle movement (Pseudocode):

for x = 0 to 1if Paddle[x] is 0 you do nothingif Paddle[x] is 1 increase PaddlePos[x] by 1if Paddle[x] is 2 decrease PaddlePos[x] by 1next x


By doing that you will always have fair chances for player and adding a 2 Player mode is easy. For an easy level add a delay for the CPU - so for example: only update the cpu paddle once in 500ms for example or make the cpu wait for next move until the player touched the ball. (If you have an exact check if the cpu will reach the ball and the paddle movement instantly changes the cpu will ALWAYS win)
Advertisement
You could also add a random "overcorrection" error, and you could have three AI states" complacent (AI undercorrects) Normal (AI won't make any mistakes) and Panic (AI will overcorrect). These states are invoked depending on the distance from the ball to the AI, and the speed the ball is moving.
I just wanted to see if he would actually do it. Also, this test will rule out any problems with system services.

This topic is closed to new replies.

Advertisement