Rebound

Program Rebound is more advanced, using a buffer to store the object. Five lines of advanced code to handle the buffer need explanation.

  1. MemoryBall := imageSize(0, 0, Diameter, Diameter);

    The white ball to be copied has been drawn at the top left of the window. The amount of memory required to hold it is needed for the following line of code.

  2. getMem(PBall, MemoryBall); //Reserve the buffer of size MemoryBall.

    The reserved memory will be accessed using the pointer PBall.

  3. getImage(0, 0, Diameter, Diameter, PBall^); //Copy image to buffer

    The image of the ball is copied to a buffer starting at the address held in the pointer PBall. The caret character (^) dereferences the pointer, causing the address it holds to be used to retrieve data.

  4. putImage(X, Y, PBall^, CopyPut);

    The image is copied from the buffer to coordinate (X,Y) of the graphics window. The fourth argument controls how the image is copied. In this case it is a simple copy, but each pixel could be be subjected to a Boolean operation with the corresponding pixel in the background by using the argument XORPut, ORPut, AndPut or NotPut.

  5. freeMem(PBall, MemoryBall);

    The memory reserved by the program should be freed by the program when no longer needed.

We think that the bar procedure for redrawing the background is quick, but you may want to try storing a black image in a buffer and use that instead of bar.

program Rebound;
  {$mode objfpc}{$H+}
uses
  SysUtils, Graph;
const
  SLEEP_TIME = 20;
  DIAMETER = 10;
  X_MOVE_DIST = 5;
  Y_MOVE_DIST = 5;
  X_MAX = 240;
  Y_MAX = 240;
  Y_START = 100;
var
  Gd, Gm : smallint;
  Error, X, Y, Radius, i : integer;
  PBall : pointer;
  MemoryBall : word;
  RightNext, DownNext : Boolean;

procedure Move;
begin
  //Calculate new X co-ordinate
  if RightNext then
    begin
      if X + Diameter >= X_MAX then
        begin
          RightNext := False;
          X := X - X_MOVE_DIST;
        end
      else
        begin
          X := X + X_MOVE_DIST;
        end;
    end
  else //Moving left
    begin
      if X <= 0 then
        begin
          RightNext := True;
          X := X + X_MOVE_DIST;
        end
      else
        begin
          X := X - X_MOVE_DIST;
        end;
    end;
  //Calculate new Y co-ordinate
  if DownNext then
    begin
      if Y + Diameter >= Y_MAX then
        begin
          DownNext := False;
          Y := Y - Y_MOVE_DIST;
        end
      else
        begin
          Y := Y + Y_MOVE_DIST;
        end;
    end
  else //Moving up
    begin
      if Y <= 0 then
        begin
          DownNext := True;
          Y := Y + Y_MOVE_DIST;
        end
      else
        begin
          Y := Y - Y_MOVE_DIST;
        end;
    end;
  //Draw the ball
  putImage(X, Y, PBall^, 0);
  //fillEllipse(X + Radius, Y + Radius, Radius, Radius); 
  sleep(SLEEP_TIME);
  //Delete the ball
  bar(X, Y, Diameter + X, Diameter + Y);
end;

begin
  //Open a 640 x 480 pixel, 16 colour graph window
  Gd := D4bit;
  Gm := m640x480;
  initGraph(Gd, Gm, '');
  //Check graphResult
  Error := graphResult;
  if (error <> grOk) then
    begin
      writeln('640 x 480 x 16 is not supported.');
      sleep(5000);
      halt;
    end;
  //Draw a white ball at the top left of the screen.
  setFillStyle(SolidFill, White);
  Radius := Diameter DIV 2;
  fillEllipse(Radius, Radius, Radius, Radius);
  //Find the memory required to hold it in a buffer
  MemoryBall := imageSize(0, 0, Diameter, Diameter);
  getMem(PBall, MemoryBall); //Reserve the buffer of size MemoryBall.
  getImage(0, 0, Diameter, Diameter, PBall^); //Copy image to buffer
  //Delete the ball, which was drawn there only to be copied.
  setFillStyle(SolidFill, Black);
  bar(0, 0, Diameter, Diameter);
  //Draw 2 sides of the container
  line(X_MAX + 1, 0, X_MAX + 1, Y_MAX + 1);
  line(0, Y_MAX + 1, X_MAX + 1, Y_MAX + 1);
  //Initialize
  X := 0;
  Y := Y_START;
  DownNext := True;
  RightNext := True;
  //Move the ball
  for i := 1 to 500 do
    begin
      Move;
    end;
  //Free the buffer
  freeMem(PBall, MemoryBall);
  closeGraph;
  write('Please press return to exit. ');
  readln;
end.
Programming - a skill for life!

Introduction to Motion Graphics