oreilly.comSafari Books Online.Conferences.


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

Before genSlope() can generate any random numbers, it must seed the random number generator. If it does not, the first call to rand() will automatically seed the random number generator with 1, which seems OK, except for the fact that you will get the same sequence of "random" numbers every time you start the game. It does not take much thinking about this to see why that would defeat the entire purpose behind randomly generating the slope in the first place. So seed the random number generator we must, and what better to seed it with than the current timestamp? (To answer that question, a few bytes from /dev/random would be better to seed it with, but we will refrain in the interest of portability, as /dev/random does not exist on all systems.) The time() function helpfully returns the current Unix epoch time (which is the number of seconds that have elapsed since January 1, 1970), so you can just feed it directly into the gaping maw of the srand() function, as shown in this excerpt from genSlope():

  // Seed the random number generator with the current Unix timestamp
  srand( time( NULL ) );

Now that the diabolical hunger of the random number generator is sated, you can use it to generate the change-in-y portion of the slope:

  // Generate the change-in-y component of the slope randomly
  slope->dy = 1 + (game->slope_max_dy * rand() / (RAND_MAX + 1.0));

This is a lot more complicated than it should be, as rand() likes to generate numbers between 0 and the C-library-defined macro RAND_MAX, which is typically a large number like 32,767. What you really want is an integer between 1 and the maximum allowable value for dy, so you must divide the value returned by rand() by RAND_MAX plus 1 to get a floating point number between 0 and 1, then multiply that by the aforementioned slope_max_dy, and finally, add 1 to the whole bloody thing. Luckily, computing the change-in-x part of the slope is much easier:

  // The change-in-x component of the slope is
  // whatever is left in the "budget"
  slope->dx = game->ball_speed - slope->dy;

Things should start to become clear now: we want the ball to move six pixels a turn, and we will generate the number of pixels it moves in the y direction randomly, and use the rest for x-centric movement (pun intended, sorry about that). And finally, to make sure the ball does not always move down and to the right from the start, have genSlope() randomly flip the sign on one or both components of the slope:

  // Flip a coin for x and y directions
  if ((int)(2.0 * rand() / (RAND_MAX + 1.0)))
    slope->dx *= -1;
  if ((int)(2.0 * rand() / (RAND_MAX + 1.0)))
    slope->dy *= -1;

(At this point, it becomes obvious that the "slope" is not truly a slope, because in the realm of SDL Pong, a slope of -1/-1 is not the same as a slope of 1/1; that's OK, however.)

Now all you have to do is make sure the genSlope() function gets called at some point. Right after the call to resetSprites(), but before we enter the black hole that is the main loop, would seem a logical choice:

  // Initialise our sprite locations
  resetSprites( &game, 0 );
  // Randomly generate the starting slope
  genSlope( &game );

  // Main loop
  while (1) {

At this point, however, you have nothing to show for all of your hard work on slope-related issues, as the ball still does not move.

Adding a call to the moveBall() function right before the delay and the end of the main loop should do the trick:

    // Move the ball
    moveBall( &game );

    // Give the CPU a break
    SDL_Delay( GAME_SPEED );
  } // while (main loop)

That is, it should do the trick once you add a function definition to the top of the file:

// Function definitions
int  cleanUp( int err );
void genSlope( GameData *game );
void moveBall( GameData *game );
void movePaddle( GameData *game, int player, int dir );
void resetSprites( GameData *game, int erase );

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 Kernel Archives
  • Kernel Traffic

  • Sponsored by: