Pong Extra: Making an Enemy Paddle
In my last Pong post, I went over the basic mechanics of the game and introduced a tunable version that you can independently experiment with. I want to talk about some bonus features that I added to the BrowPong program that were not in the original game.
I'll start with how I made your BrowPong nemesis, the computer player. As before, the executable will include presets that you can use to reproduce the game states I demonstrate here.
Now pong is not like chess or Tetris. You don’t need a supercomputer or a machine learning algorithm to create a challenging computer opponent. In fact, you can create a mistake-free computer player with nothing more than a little middle school mathematics. Imagine a ball moving along a straight line towards a player‘s goal. To return the ball, I just need to move the computer player to the location where that straight line intersects the computer player's goal. In the language of mathematics, I need to compute the “y intercept” (y2 in the above diagram). \[y_2=y_1 + (x_2-x_1) \frac{v_y}{v_x}\] At any given time, the game keeps track of everything on the right side of the equation above - the ball's position (x1, y1), the ball's velocity (vx, vy) and the x position of the computer's goal (x2). So it's just plug and chug inside the program.
Here is what happens when I add that logic to the right hand player in a game of pong (preset "One Player Computer No Bounce"). Looks fine, right? I’m done already, blog post over!
Ok, nah, there’s more to this. It's true that the computer can sniff out the location of any ball coming straight towards it, but there's another case to consider. You see, the ball doesn't always come straight at the computer. If I want it to avoid mistakes, I need it to be able to anticipate bounces off the walls. The logic to do that is a bit more complicated, but still only involves simple mathematics.
Basically, what I have to do is start by computing the point where the ball intersects the top wall (or bottom bottom wall, if it’s moving downward). If I find that the ball's trajectory intersects the top/bottom wall inside the playing field, that means the ball is going to bounce before it reaches the computer player. In that case, I need to compute the Y intercept starting from the position of the bounce rather than the ball’s current position. \[x_2=x_1 + (y_2-y_1) \frac{v_x}{v_y}\] \[y_3=y_2 - (x_3-x_2) \frac{v_y}{v_x}\] Once I put the first equation in for x2 in the second equation, I have a single expression that computes the position of a bounced ball (I won't expand the expression here). Everything else on the right side of these equations is tracked by the program, including the ball's position (x1, y1), the ball's velocity (vx, vy), the y position of the top wall (y2), and the x position of the computer's goal (x3).
Now I can make a mistake-free player! (Also, no more math the rest of the way, I promise.)
I want to make the computer good, but fallible. It can’t just be hitting perfectly centered shots every time, you want it to hit off the edges and even miss sometimes. A simple way of doing this is to just add a random error in the position of the computer paddle. Let's watch a pair of computer players go at it with a random offset in the paddle (preset "Computer Offset No Mistakes"). Notice how the paddle offsets have the bonus benefit of adding more high-angle shots, which makes the game more fun to watch and play.
It still doesn't look very... human, however. For one thing, the paddles jump to their target positions without adjustment or hesitation. But the bigger problem is the computer's mistakes. It's weird to see the computer respond successfully to fast, high-angle shots and then misalign itself on a simple straight shot. To prevent this (or at least, make it less common), I added an additional parameter to the AI algorithm that increases the average computer error as the speed of the ball increases in the vertical direction. And to make it look a little more human, I added a chance that the computer will make an adjustment in any given frame.
Here's what it looks like when everything is put together (preset "Zero Player Standard"). As a side note, if you want to try facing off with the "mistake-free" computer player, you can use the "One Player Computer No Mistakes" setting. While it's impossible for the computer to misalign itself, you might still be able to beat it. After all, there is a limit to how fast the paddle can move...
I'll start with how I made your BrowPong nemesis, the computer player. As before, the executable will include presets that you can use to reproduce the game states I demonstrate here.
The Computer Player
The original Pong was a two-player game, but many of the subsequent ports and clones included a one-player option.Now pong is not like chess or Tetris. You don’t need a supercomputer or a machine learning algorithm to create a challenging computer opponent. In fact, you can create a mistake-free computer player with nothing more than a little middle school mathematics. Imagine a ball moving along a straight line towards a player‘s goal. To return the ball, I just need to move the computer player to the location where that straight line intersects the computer player's goal. In the language of mathematics, I need to compute the “y intercept” (y2 in the above diagram). \[y_2=y_1 + (x_2-x_1) \frac{v_y}{v_x}\] At any given time, the game keeps track of everything on the right side of the equation above - the ball's position (x1, y1), the ball's velocity (vx, vy) and the x position of the computer's goal (x2). So it's just plug and chug inside the program.
Here is what happens when I add that logic to the right hand player in a game of pong (preset "One Player Computer No Bounce"). Looks fine, right? I’m done already, blog post over!
Ok, nah, there’s more to this. It's true that the computer can sniff out the location of any ball coming straight towards it, but there's another case to consider. You see, the ball doesn't always come straight at the computer. If I want it to avoid mistakes, I need it to be able to anticipate bounces off the walls. The logic to do that is a bit more complicated, but still only involves simple mathematics.
Basically, what I have to do is start by computing the point where the ball intersects the top wall (or bottom bottom wall, if it’s moving downward). If I find that the ball's trajectory intersects the top/bottom wall inside the playing field, that means the ball is going to bounce before it reaches the computer player. In that case, I need to compute the Y intercept starting from the position of the bounce rather than the ball’s current position. \[x_2=x_1 + (y_2-y_1) \frac{v_x}{v_y}\] \[y_3=y_2 - (x_3-x_2) \frac{v_y}{v_x}\] Once I put the first equation in for x2 in the second equation, I have a single expression that computes the position of a bounced ball (I won't expand the expression here). Everything else on the right side of these equations is tracked by the program, including the ball's position (x1, y1), the ball's velocity (vx, vy), the y position of the top wall (y2), and the x position of the computer's goal (x3).
Now I can make a mistake-free player! (Also, no more math the rest of the way, I promise.)
Humanizing the Computer
While I just created a mistake-free computer player, that’s not what I want, is it?. After all, who wants to play against an opponent that can’t miss?I want to make the computer good, but fallible. It can’t just be hitting perfectly centered shots every time, you want it to hit off the edges and even miss sometimes. A simple way of doing this is to just add a random error in the position of the computer paddle. Let's watch a pair of computer players go at it with a random offset in the paddle (preset "Computer Offset No Mistakes"). Notice how the paddle offsets have the bonus benefit of adding more high-angle shots, which makes the game more fun to watch and play.
It still doesn't look very... human, however. For one thing, the paddles jump to their target positions without adjustment or hesitation. But the bigger problem is the computer's mistakes. It's weird to see the computer respond successfully to fast, high-angle shots and then misalign itself on a simple straight shot. To prevent this (or at least, make it less common), I added an additional parameter to the AI algorithm that increases the average computer error as the speed of the ball increases in the vertical direction. And to make it look a little more human, I added a chance that the computer will make an adjustment in any given frame.
Here's what it looks like when everything is put together (preset "Zero Player Standard"). As a side note, if you want to try facing off with the "mistake-free" computer player, you can use the "One Player Computer No Mistakes" setting. While it's impossible for the computer to misalign itself, you might still be able to beat it. After all, there is a limit to how fast the paddle can move...
Comments
Post a Comment