LinuxDevCenter.com
oreilly.comSafari Books Online.Conferences.

advertisement


Retro Gaming Hacks, Part 3: Add a Ball and Score to Pong
Pages: 1, 2, 3, 4, 5, 6

Now, you need to initialize the score to 0-0, and the number of points for a win to GAME_POINTS:

  // Initialise game data
  game.running           = 1;
  game.ball_speed        = BALL_SPEED;
  game.slope_max_dy      = SLOPE_MAX_DY;
  game.p1_speed          = P1_SPEED;
  game.p2_speed          = P2_SPEED;
  game.num_rects         = 0;
  game.score.p1          = 0;
  game.score.p2          = 0;
  game.score.game_points = GAME_POINTS;

Right after initializing SDL in your code, add:

  // Initialise TTF engine and load a font
  TTF_Init();
  if ((game.font = TTF_OpenFont( MSG_FONT, MSG_SIZE )) == NULL) {

    fprintf( stderr, "Could not open font: %s\n", MSG_FONT );
    return cleanUp( 2 );
    
  } // if (could not load font)

This performs whatever initialization SDL_TTF requires, and then attempts to load the MSG_FONT font and scale it to the proper size. Calling TTF_Init() introduces a slight new wrinkle: you must tear down SDL_TTF before exiting the program. No problem; you can just add a line to the cleanUp() function:

int cleanUp( int err ) {

  TTF_Quit();
  SDL_Quit();

  return err;

} // cleanUp()

Now, all of the remaining action is set in the moveBall() function; specifically inside that else/if block that used to just reset the sprites and regenerate the slope. Let's add scorekeeping code to this block:

  // 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)) {

    SDL_Color white = { 0xff, 0xff, 0xff, 0 };
      
    SDL_Rect rect_msg      = { SCREEN_WIDTH / 2 - 90, 100, 200, 50 };
    SDL_Rect rect_score_p1 = { 100,                   200, 150, 50 };
    SDL_Rect rect_score_p2 = { SCREEN_WIDTH - 200,    200, 150, 50 };

    SDL_Rect rects[3];
    
    char str_msg[32], str_score_p1[16], str_score_p2[16];
    SDL_Surface *text_msg, *text_score_p1, *text_score_p2;

    if (game->ball.x < 0)
      game->score.p2++;
    else if (game->ball.x > (SCREEN_WIDTH - game->ball.w))
      game->score.p1++;

    // Write scoring messages
    snprintf( str_msg, 32, "Player %d scores!", 
      ((game->ball.x < 0) ? 2 : 1) );

    snprintf( str_score_p1, 16, "Player 1: %d", game->score.p1 );
    snprintf( str_score_p2, 16, "Player 2: %d", game->score.p2 );

    text_msg      = TTF_RenderText_Solid( game->font, str_msg,      
        white );
    text_score_p1 = TTF_RenderText_Solid( game->font, str_score_p1, 
        white );
    text_score_p2 = TTF_RenderText_Solid( game->font, str_score_p2, 
        white );
    
    // Display scoring messages
    rects[0] = rect_msg;
    rects[1] = rect_score_p1;
    rects[2] = rect_score_p2;

    SDL_BlitSurface( text_msg,      NULL, game->screen, 
        &rect_msg      );
    SDL_BlitSurface( text_score_p1, NULL, game->screen, 
        &rect_score_p1 );
    SDL_BlitSurface( text_score_p2, NULL, game->screen, 
        &rect_score_p2 );

    SDL_UpdateRects( game->screen, 3, rects );

    // Display the score for awhile
    SDL_Delay( MSG_TIME );

    // Erase scoring messages
    SDL_FillRect( game->screen, &rect_msg,      game->black );
    SDL_FillRect( game->screen, &rect_score_p1, game->black );
    SDL_FillRect( game->screen, &rect_score_p2, game->black );
    
    SDL_UpdateRects( game->screen, 3, rects );

    // Has someone just won the game?
    if (game->score.p1 == game->score.game_points ||
        game->score.p2 == game->score.game_points) {

      // Display the final score
      snprintf( str_msg, 32, "Player %d wins!",
                ((game->ball.x < 0) ? 2 : 1) );

      snprintf( str_score_p1, 16, "Player 1: %d", game->score.p1 );
      snprintf( str_score_p2, 16, "Player 2: %d", game->score.p2 );

      text_msg      = TTF_RenderText_Solid( game->font, str_msg,      
        white );
      text_score_p1 = TTF_RenderText_Solid( game->font, str_score_p1, 
        white );
      text_score_p2 = TTF_RenderText_Solid( game->font, str_score_p2, 
        white );
    
      rects[0] = rect_msg;
      rects[1] = rect_score_p1;
      rects[2] = rect_score_p2;

      SDL_BlitSurface( text_msg,      NULL, game->screen, 
        &rect_msg      );
      SDL_BlitSurface( text_score_p1, NULL, game->screen, 
        &rect_score_p1 );
      SDL_BlitSurface( text_score_p2, NULL, game->screen, 
        &rect_score_p2 );

      SDL_UpdateRects( game->screen, 3, rects );

      // Pause for awhile
      SDL_Delay( MSG_TIME * 2 );

      // End the game
      game->running = 0;
      return;
      
    } // if (game over!)

The goal of all of this code is simply to display three messages at different locations on the screen. When a player scores, the game displays "Player X scores!" in the top center of the screen, and then each player's new score on his side of the screen. This is accomplished with the help of a slew of local variables: three SDL_Rect structures, one for each message (the in-line initialization may be new to some of you; the first field of the SDL_Rect structure is the x coordinate, followed by the y coordinate, followed by the width, followed by the height); a local array of SDL_Rect structures to feed to our old friend SDL_UpdateRects(); a string for each message; and finally, an SDL_Surface pointer for each.

Pages: 1, 2, 3, 4, 5, 6

Next Pagearrow




Linux Online Certification

Linux/Unix System Administration Certificate Series
Linux/Unix System Administration Certificate Series — This course series targets both beginning and intermediate Linux/Unix users who want to acquire advanced system administration skills, and to back those skills up with a Certificate from the University of Illinois Office of Continuing Education.

Enroll today!


Linux Resources
  • Linux Online
  • The Linux FAQ
  • linux.java.net
  • Linux Kernel Archives
  • Kernel Traffic
  • DistroWatch.com


  • Sponsored by: