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.