Pascal Worked Example: Bouncing Ball: Iteration 1

From SwinBrain

In this iteration I plan to implement the drawing of the borders for the game.

Contents

Data Required

This iteration will require the definition for the area of the game. This can be done using constants within the program. The following code snippet shows the constants required to define this area. The BORDER_X constant indicates the border on the left of the screen.

const
  BORDER_START_X = 2;
  BORDER_START_Y = 2;
  BORDER_WIDTH = 80 - BORDER_START_X - 1; //-1 for right border
  BORDER_HEIGHT = 25 - BORDER_START_Y - 1;
  BORDER_CHARACTER = #178;

Structure

We will structure the program with Main and DrawBorder routines.

  • Main: This will just call DrawBorder
  • DrawBorder: This will implement the logic required to draw the border on the screen. This will access the constants defined above, and will create x and y local variables to loop over the range required to draw the border.

DrawBorder

The DrawBorder routine will draw the four borders around the area where the ball will bounce.

for x := leftPosition to rightPos do
  GotoXY x, topPosition
  Write border character
 
  GotoXY x, bottomPosition
  Write border character
end
 
for y := topPosition to bottomPos do
  GotoXY leftPosition, y
  Write border character
 
  GotoXY rightPosition, y
  Write border character
end

Cut 1

The first cut of this program draws only the top and bottom borders. This is shown in the following code snippet.

//This is a game where a ball is placed within a designated
//area of the screen. The ball will have a specified velocity
//and will move around within the area. When the ball collides
//with the edge of the area it should change direction. 
//Striking the bottom/top of the area will reverse the y 
//movement, while striking the left/right will reverse the
//x movement.
program BouncingBall;
uses CRT;
 
const
  BORDER_START_X = 2;
  BORDER_START_Y = 2;
  BORDER_WIDTH = 80 - BORDER_START_X - 1; //-1 for right border
  BORDER_HEIGHT = 25 - BORDER_START_Y - 1;
  BORDER_CHARACTER = #178;
 
//Draws the border around the game area.
//
// @param title The title to be written above the border
//
//Side Effects:
// * Writes to the console
procedure DrawBorder(title: String);
var
  x, y: Integer;
begin
 
  //Draw the top + bottom borders
  for x := BORDER_START_X to BORDER_START_X + BORDER_WIDTH do
  begin
    //Top
    y := BORDER_START_Y;
    GotoXY(x, y);
    Write(BORDER_CHARACTER);
    
    y := BORDER_START_Y + BORDER_HEIGHT;
    GotoXY(x, y);
    Write(BORDER_CHARACTER);
  end;
 
end;
 
procedure Main();
begin
  DrawBorder('Bouncing Ball');
end;
 
begin
  Main();
end.

Basically this code uses a for loop to move the X value from the left position to the right position and at each step it draws the border character at the specified X position both at the top and bottom of the area.

Cut 1 execution


Cut 2

The next cut added the code to draw the left and right borders. The code for this is basically the same as the code for drawing the top and bottom lines.

//This is a game where a ball is placed within a designated
//area of the screen. The ball will have a specified velocity
//and will move around within the area. When the ball collides
//with the edge of the area it should change direction. 
//Striking the bottom/top of the area will reverse the y 
//movement, while striking the left/right will reverse the
//x movement.
program BouncingBall;
uses CRT;
 
const
  BORDER_START_X = 2;
  BORDER_START_Y = 2;
  BORDER_WIDTH = 80 - BORDER_START_X - 1; //-1 for right border
  BORDER_HEIGHT = 25 - BORDER_START_Y - 1;
  BORDER_CHARACTER = #178;
 
//Draws the border around the game area.
//
// @param title The title to be written above the border
//
//Side Effects:
// * Writes to the console
procedure DrawBorder(title: String);
var
  x, y: Integer;
begin
  GotoXY(BORDER_START_X, 1);
  Write(Title);
  //Draw the top + bottom borders
  for x := BORDER_START_X to BORDER_START_X + BORDER_WIDTH do
  begin
    //Top
    y := BORDER_START_Y;
    GotoXY(x, y);
    Write(BORDER_CHARACTER);
    
    y := BORDER_START_Y + BORDER_HEIGHT;
    GotoXY(x, y);
    Write(BORDER_CHARACTER);
  end;
  
  for y := BORDER_START_Y to BORDER_START_Y + BORDER_HEIGHT do
  begin
    x := BORDER_START_X;
    GotoXY(x, y);
    Write(BORDER_CHARACTER);
  	
    x := BORDER_START_X + BORDER_WIDTH;
    GotoXY(x, y);
    Write(BORDER_CHARACTER);
  end;
end;
 
procedure Main();
begin
  DrawBorder('Bouncing Ball');
end;
 
begin
  Main();
end.

At this point we have achieved the desired goal for this iteration. The border is being displayed. The image below shows the execution at this point.

The execution after cut 2


Refactoring

At the end of this iteration we can examine the code to see if there is any need to refactor it in any way. Examining the code we can see that there is some code that is repeated a number of times. This could be refactored into its own routine. Specifically the following code appears multiple times:

GotoXY(x, y);
  Write(BORDER_CHARACTER);

We can move this into its own procedure called DrawBorderAt that will accept the X, and Y coordinates. The final version for this code is then shown below.

//This is a game where a ball is placed within a designated
//area of the screen. The ball will have a specified velocity
//and will move around within the area. When the ball collides
//with the edge of the area it should change direction. 
//Striking the bottom/top of the area will reverse the y 
//movement, while striking the left/right will reverse the
//x movement.
program BouncingBall;
uses CRT;
 
const
  BORDER_START_X = 2;
  BORDER_START_Y = 2;
  BORDER_WIDTH = 80 - BORDER_START_X - 1; //-1 for right border
  BORDER_HEIGHT = 25 - BORDER_START_Y - 1;
  BORDER_CHARACTER = #178;
  
//Draws a border character at a given XY location.
//
// @param X The x location to draw at
// @param Y The y location to draw at
// 
//Side Effects:
// * Draws to the screen
procedure DrawBorderAt(x, y: Integer);
begin
  GotoXY(x, y);
  Write(BORDER_CHARACTER);
end;
 
//Draws the border around the game area.
//
// @param title The title to be written above the border
//
//Side Effects:
// * Writes to the console
procedure DrawBorder(title: String);
var
  x, y: Integer;
begin
  GotoXY(BORDER_START_X, 1);
  Write(Title);
  
  //Draw the top + bottom borders
  for x := BORDER_START_X to BORDER_START_X + BORDER_WIDTH do
  begin
    //Top
    DrawBorderAt(x, BORDER_START_Y);
    DrawBorderAt(x, BORDER_START_Y + BORDER_HEIGHT);
  end;
  
  for y := BORDER_START_Y to BORDER_START_Y + BORDER_HEIGHT do
  begin
    DrawBorderAt(BORDER_START_X, y);
    DrawBorderAt(BORDER_START_X + BORDER_WIDTH, y);
  end;
end;
 
procedure Main();
begin
  DrawBorder('Bouncing Ball');
end;
 
begin
  Main();
end.

Summary

This iteration has added the code to draw the border around the edge of the screen, and display a title above this border. The next step will be to get the ball to appear and move on the screen.

[edit]Bouncing Ball: Overview | Iteration 1 | Iteration 2 | Iteration 3 | Iteration 4
Sample Code » C | C++ | .NET | Pascal | Perl | T-Sql | XHTML | Python | others to come