Complete program listing

A complete listing of the program is shown in Listing 10.

Listing 10. Source code for program named BouncingBall02.
/*Project BouncingBall02
This is an update of the earlier program named
BouncingBallInBox.

This update illustrates two important aspects of smooth
animation:

1. Drawing the animated ball on an off-screen buffer and
calling the blit function to copy the contents of the
buffer to the screen once during each animation cycle.
2. Moving an object in front of a background that is
an image instead of a solid color as was the case in the
earlier version of the program.

Displays a ball bouncing around inside of a box. The
ball is allowed to move in only four directions:
northeast, southeast, southwest, or northwest. When the
ball hits a wall of the box, it doesn't bounce in the
direction that would normally be expected.  Instead it
selects one of the four possible directions and bounces
in that direction.

The ball continues to bounce until the user presses the
Esc key, at which point the program terminates.
*/

#include <allegro.h>

//Declare a pointer variable named buffer that can be
// used to point to a BITMAP. This will be the main
// memory buffer containing an image.
BITMAP *buffer = NULL;

//Declare another pointer variable named smallBuffer that
// can also be used to point to a BITMAP. This memory
// buffer will be used to save a small square area of the
// large image centered on the ball. The small image will
// be used to restore the area of the image occupied by
// the ball when it is time for the ball to move to a
// new location.
BITMAP *smallBuffer = NULL;

//Note that the size of the image was known before the
// program was written, and that size is used below to
// set the size of the box.
int width = 324;//width of box
int height = 330;//height of box
int radius = 9;//radius of ball

int x = 100;//initial position of ball
int y = 200;//initial position of ball

int tempX;//used to save the current location of the ball
int tempY;//used to save the current location of the ball

//Keep track of direction of motion here.
//0= northwest 1 = southwest, 2 = northeast,
//3 = southeast
int dir;
//------------------------------------------------------//

void moveBall(){
  //Save current location of ball.
  tempX = x;
  tempY = y;

  //The code in the switch statement is identical to the
  // code in the earlier version of the program.
  switch(dir){
    case 0:
      //Direction is northwest.
      if((x <= radius) || (y <= radius)){
        //Ball has collided with either the left wall or
        // the top wall.
        //Get a new direction. Note that if the new
        // direction is the same as the old one, control
        // will come back to here to get still another
        // direction the next time the function is called.
        dir = rand() % 4;
      }else{
        //No collision, set new location for the ball
        --x;
        --y;
      }//end else
    break;
    case 1:
      //Direction is southwest.
      if(((x <= radius) || (y >= (height - radius)))){
        //get a new direction
        dir = rand() % 4;
      }else{
        //set new location for the ball
        --x;
        ++y;
      }//end else
    break;
    case 2:
      //Direction is northeast.
      if(((x >= (width - radius)) || (y <= radius))){
        //get a new direction
        dir = rand() % 4;
      }else{
        //set new location for the ball
        ++x;
        --y;
      }//end else
    break;
    case 3:
      //Direction is southeast
      if((((x >= (width - radius)) ||
                              (y >= (height - radius))))){
        //get a new direction
        dir = rand() % 4;
      }else{
        //set new location for the ball
        ++x;
        ++y;
      }//end else

  }//end switch

  //Erase the current image of the ball by drawing the
  // saved background over the ball.
  blit(smallBuffer,buffer,
       0,0,
       tempX-radius-1,tempY-radius-1,
       radius*2+2,radius*2+2);

  //Save a square area of the background at the new
  // location of the ball before the ball is drawn there.
  // Each side of the square is two pixels larger than the
  // diameter of the ball to allow for the possibility
  // that the ball isn't perfectly centered in the square.
  blit(buffer,smallBuffer,
       x-radius-1,y-radius-1,
       0,0,
       radius*2+2,radius*2+2);

  //Now draw the ball on the background at the new
  // location.
  circlefill (buffer,x,y,radius,makecol(255,0,0));

  //Call the blit function to copy the off-screen buffer
  // contents to the screen.
  blit(buffer,screen,0,0,0,0,width,height);

  rest(5);//Delay for five milliseconds
}// end moveBall function.
//------------------------------------------------------//

int main(){

  allegro_init();
  install_keyboard();
  set_color_depth(32);
  set_gfx_mode(GFX_AUTODETECT_WINDOWED,width,height,0,0);

  //Load an image file from the current directory.
  buffer = load_bitmap("starfish324x330.pcx", NULL);
  
  //Create an empty bitmap and store its address in
  // smallBuffer. Make the width and height equal to the
  // diameter of the ball plus two pixels.
  smallBuffer = create_bitmap(radius*2 + 2,radius*2 + 2);
  
  //Save a square area of the background at the current
  // location of the ball. Each side of the square is two
  // pixels larger than the diameter of the ball to allow
  // for the possibility that the ball isn't perfectly
  // centered in the square.
  blit(buffer,smallBuffer,
       x-radius-1,y-radius-1,
       0,0,
       radius*2+2,radius*2+2);

  //Seed the random number generator and set the initial
  // direction based on a random number.
  srand (time(NULL));
  dir = rand() % 4;
  //Loop until the user presses the Esc key.
  while( !key[KEY_ESC]){
    moveBall();
  }//end while loop

  return 0;
}//end main
END_OF_MAIN();