Retro Gaming Hacks, Part 3: Add a Ball and Score to Pong
Pages: 1, 2, 3, 4, 5, 6
and then implement the moveBall() function:
/* Function: moveBall()
*
* Moves the ball.
*
* Parameters:
*
* *game - game data
*/
void moveBall( GameData *game ) {
// Erase the current ball
SDL_FillRect( game->screen, &(game->ball), game->black );
game->rects[game->num_rects++] = game->ball;
// Move the ball (reset height and width, as going off the screen seems
// to compress them)
game->ball.x += game->slope.dx;
game->ball.y += game->slope.dy;
game->ball.w = BALL_W;
game->ball.h = BALL_H;
// If the ball hits the top or bottom wall, bounce it
if (game->ball.y <= 0 || game->ball.y >= (SCREEN_HEIGHT - game->ball.h)) {
// Add a sound effect here?
// According to my grade eight geometry class, "the angle of refraction
// equals the angle of incidence" (thanks, Mrs. Lott!), so let's just
// multiply the y component of our slope by -1 to change its sign
game->slope.dy *= -1;
} // if (ball bouncing off top or bottom wall)
// If the ball has hit a player's paddle, bounce it
if (((game->ball.x <= game->p1.w) &&
(game->ball.y >= game->p1.y &&
((game->ball.y + game->ball.h) <= game->p1.y + game->p1.h))) ||
(game->ball.x >= (SCREEN_WIDTH - (game->p2.w + (game->ball.w))) &&
(game->ball.y >= game->p2.y &&
((game->ball.y + game->ball.h) <= game->p2.y + game->p2.h)))) {
// Add a sound effect here?
// Multiply the x component of our slope by -1 to change its sign; see
// note above on elementary geometry
game->slope.dx *= -1;
} // if (bouncing off paddle)
// If the ball hits the left or right wall, score a point for the
// appropriate player and return the ball to the centre
else if (game->ball.x < 0 || game->ball.x > (SCREEN_WIDTH - game->ball.w)) {
// Return the paddles and ball to their starting positions
resetSprites( game, 1 );
// Generate a new slope
genSlope( game );
} // else if (score!)
SDL_FillRect( game->screen, &(game->ball), game->white );
game->rects[game->num_rects++] = game->ball;
} // moveBall()
The beginning of the function is trivial stuff to us by now: erase the ball by filling the rectangle corresponding to its current location with the background color, then adding the change-in-x slope component to the ball's x coordinate and the change-in-y to its y coordinate. (We reset the width and height of the ball here because going off of the screen seems to squash the ball in some cases, so better safe than sorry.)
It is when the ball hits the top or bottom of the screen (and you know this by the y coordinate--if it is less than or equal to 0, it hits the top, and greater than or equal to SCREEN_HEIGHT minus ball height, it is the bottom--just as the paddles worked) that we will whip out the second law of geometry: the angle of refraction equals the angle of incidence. This is easy, because all you need to do is flip the sign on the dy component of the slope, which keeps the angle the same, just reverses the direction.
You must do the same thing, except to dx, when the ball collides with a player's paddle. Instead of trying to explain in prose the complicated conditional conundrum that I use for detecting such a collision, I invite you to turn once again to your trusty scratch paper, and draw the requisite shapes. All should be made clear, including the bug in my collision detection algorithm that I dubbed a feature, since it gives enterprising readers of this hack something productive to do right away. Read the last section of this hack for more details on my laziness-slash-goodwill.