bitmap motion

       The basic way to move an image across a background image is this. First, you create a monochrome bitmap the same size as the moving image, with the black silhouette of the e.g. airplane against a white background - call this the mask. You also must create a same-sized bitmap to hold the portion of the background that you'll be overwriting - call it the storage. Then the process of making one movement of the image goes like this:

       1) copy storage onto background at its old location
       2) copy a rectangle from background to storage at new location
       3) copy the image to the background using SRCINVERT
       4) copy the mask to the background using SRCAND
       5) copy the image to the background again using SRCINVERT

       Nasty? Well, perhaps, but that's the way it's done. Copying an image with SRCINVERT XORs the pixels with the background. XOR the same image twice and you return to the original background. But because we ANDed the mask between the two XORs, the black part of the mask contains whatever was in the image with no trace of the background.

       Here's the catch. These operations can all be handled using CopyRect, but there's an impossibly annoying flicker of the entire background image. I'm not a big graphics dude; I couldn't figure out how to eliminate the flicker. So it seems you'd have to go down to the metal and use the Windows API function BitBlt.

Here is an example of using this:

  This project animates a 32 x 32 bitmap, defined in "Mymask.bmp" and "Mybmp.bmp", that replaces the mouse cursor. We could have replaced the  cursor itself with a resource, but replacing the mouse cursor with a sprite allows a demonstration of animation with minimal logic controlling  sprite location.

  The demo does have a great deal of flicker.  I have not employed screen swapping in this demo -- the demo is as minimal as I could make it, to demonstrate just the basic technique.

  The bitmap used for this project looks roughly like a blue marble. Two 32 x 32 pixel, 16 color bitmaps were created in the image editor by the following method:
    1) Create mask by drawing a black circle and saving in the project directory as "Mymask.bmp".
    2) Copy this bitmap as "MyBMP.bmp".
    3) Color the black area as blue and perform any other enhancements on the blue area (such as a tiny white square in the "marble" upper corner to suggest a shiney spot).

    Noel Rice
    Borland Technical Support
 
 

unit Anim1;

interface
 
uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs;

type

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormDestroy(Sender: TObject);
  protected
    FStorage: TBitMap;
    FMask: TBitMap;
    FImage: TBitMap;
    FOldRect: TRect;
    FNewRect: TRect;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
 

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMask := TBitMap.Create;
  FMask.LoadFromFile(ExtractFilePath(Application.ExeName) + 'MYMASK.BMP');

  FImage := TBitMap.Create;
  FImage.LoadFromFile(ExtractFilePath(Application.ExeName) + 'MYBMP.BMP');

  FStorage := TBitMap.Create;
  FStorage.Width := FImage.Width;
  FStorage.Height := FImage.Height;

  Screen.Cursor := crNone;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  FirstTime: boolean = True;
begin
  { 1) Restore Form1: copy storage onto Form1 at its old location }
  if FirstTime then FirstTime := False
  else BitBlt(Form1.Canvas.Handle, FOldRect.Left, FOldRect.Top, FImage.Width, FImage.Height,
              FStorage.Canvas.Handle, 0, 0,
              SRCCOPY);

  { save old location }
  FNewRect :=  Rect(X, Y, X + FImage.Width, Y + FImage.Height);
  FOldRect :=  FNewRect;

  { 2) Save copy of Form1: copy a rectangle from Form1 to storage
       at new location. }
  BitBlt(FStorage.Canvas.Handle, 0, 0, FImage.Width, FImage.Height,
         Form1.Canvas.Handle, FNewRect.Left, FNewRect.Top,
         SRCCOPY);

  { 3) copy the image to Form1 using SRCINVERT }
  BitBlt(Form1.Canvas.Handle, FNewRect.Left, FNewRect.Top, FImage.Width, FImage.Height,
         FImage.Canvas.Handle, 0, 0,
         SRCINVERT);

  { 4) copy the mask to Form1 using SRCAND }
  BitBlt(Form1.Canvas.Handle, FNewRect.Left, FNewRect.Top, FImage.Width, FImage.Height,
         FMask.Canvas.Handle, 0, 0,
         SRCAND);

  { 5) copy the image to Form1 again using SRCINVERT }
  BitBlt(Form1.Canvas.Handle, FNewRect.Left, FNewRect.Top, FImage.Width, FImage.Height,
         FImage.Canvas.Handle, 0, 0,
         SRCINVERT);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FMask.Free;
  FImage.Free;
  FStorage.Free;
end;

end.