home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
pascal
/
library
/
windows
/
animat
/
animate.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-06-05
|
7KB
|
222 lines
program Animate;
{$R Animate}
{This is an example to create a fast, smooth and flickerfree
animation. It uses 2 bitmaps for the sprite (the ball). One bitmap
is black in the transparent part, the other is white in the transparent
part. To keep it simple all parameters are hardcoded.
Requires BP 7.0.
Uploaded by the Autor: Hans Steinegger 100024,2730, June 4, 1994}
uses
WinTypes, WinProcs, Objects, OMemory, OWindows, ODialogs, Strings;
const
rBall = 14;
Speed = 150; {number of moves in 550 ms}
Dist = 1; {distance for 1 move}
type
tApp = object (TApplication)
procedure InitMainWindow; virtual;
function IdleAction: boolean; virtual;
end;
PMainWindow = ^TMainWindow;
TMainWindow = object (TWindow)
nUpdate, UpdateCount, MulDivVar: integer;
BallPos: tPoint;
HorDir, VerDir: boolean;
Background1, Background2, BallOr, BallAnd: hBitMap;
Old1, Old2, Old3, Old4: hBitMap;
BG1DC, BG2DC, BallAndDC, BallOrDC: hDC;
constructor Init(AParent: PWindowsObject; Title: PChar);
procedure GetWindowClass (var WndClass: TWndClass); virtual;
procedure SetUpWindow; virtual;
destructor Done; virtual;
procedure Paint (PaintDC: HDC; var PaintInfo: TPaintStruct); virtual;
procedure WMTimer (var Message: tMessage); virtual wm_First + wm_Timer;
procedure UpdateBall;
end;
constructor TMainWindow.Init(AParent: PWindowsObject; Title: PChar);
begin
TWindow.Init (AParent, Title);
Attr.W := 300;
Attr.H := 400;
Attr.Style := WS_Caption or WS_SysMenu or WS_MinimizeBox;
end;
procedure TMainWindow.GetWindowClass (var WndClass: TWndClass);
begin
TWindow.GetWindowClass(WndClass);
WndClass.hIcon := LoadIcon (hInstance, 'Animate');
end;
procedure TMainWindow.SetupWindow;
var
DC: hDC;
begin
inherited SetupWindow;
BallPos.x := 100;
BallPos.y := 100;
DC := GetDC (hWindow);
{the number of memory DC's is not as critical so
we created 4 of them here and delete them in the
Done method. This improves the speed}
{we need 2 Background images}
Background1 := LoadBitMap (hInstance, 'Background');
BG1DC := CreateCompatibleDC (DC);
Old1 := SelectObject (BG1DC, Background1);
Background2 := LoadBitMap (hInstance, 'Background');
BG2DC := CreateCompatibleDC (DC);
Old2 := SelectObject (BG2DC, Background2);
{BallOr is the bitmap of the ball with black around the ball}
BallOr := LoadBitMap (hInstance, 'BallOr');
BallOrDC := CreateCompatibleDC (DC);
Old3 := SelectObject (BallOrDC, BallOr);
{BallAnd is the bitmap of the ball with white around the ball}
BallAnd := LoadBitMap (hInstance, 'BallAnd');
BallAndDC := CreateCompatibleDC (DC);
Old4 := SelectObject (BallAndDC, BallAnd);
ReleaseDC (hWindow, DC);
if SetTimer(HWindow, 1, 550, nil) = 0 then
begin
MessageBox(HWindow, 'No Timers Left', 'Error', mb_Ok);
Halt(1);
end;
nUpdate := 0;
UpdateCount := 0;
MulDivVar := 0;
end;
destructor TMainWindow.Done;
begin
KillTimer (hWindow, 1);
SelectObject (BG1DC, Old1);
DeleteDC (BG1DC);
SelectObject (BG2DC, Old2);
DeleteDC (BG2DC);
SelectObject (BallOrDC, Old3);
DeleteDC (BallOrDC);
SelectObject (BallAndDC, Old4);
DeleteDC (BallAndDC);
DeleteObject (Background1);
DeleteObject (Background2);
DeleteObject (BallOr);
DeleteObject (BallAnd);
inherited Done;
end;
procedure TMainWindow.Paint(PaintDC: HDC;var PaintInfo: TPaintStruct);
var
MemDC: hDC;
begin
BitBlt (PaintDC, 0, 0, 300, 400, BG1DC, 0, 0, SrcCopy);
DeleteDC (MemDC);
end;
procedure TMainWindow.WMTimer (var Message: TMessage);
begin
{The minimum timer interval (55 ms) is too slow for a smooth
movement. Therefore IdleAction is used to initiate the
movement of the ball. But this 550 ms timer is used for
speed control}
nUpdate := UpdateCount;
UpdateCount := 0;
end;
procedure TMainWindow.UpdateBall;
var
x1, y1, x2, y2: integer;
Move: boolean;
DC: hDC;
OldPos: tPoint;
ClientRect: tRect;
begin
OldPos := BallPos;
inc (UpdateCount);
{First thing is to check if we have to move the ball.
A Multiply/Divide algorithm is realized with Add/Subtract}
Move := false;
if Speed >= nUpdate then Move := true
else
begin
dec (MulDivVar, Speed div Dist);
if MulDivVar < 0 then
begin
inc (MulDivVar, nUpdate);
Move := true;
end;
end;
if Move then
begin
{Check if we reached a border and invert direction
if necessary}
GetClientRect (hWindow, ClientRect);
if not HorDir and (BallPos.x - rBall <= 0) then HorDir := true;
if HorDir and (BallPos.x + rBall >= ClientRect.right) then HorDir := false;
if not VerDir and (BallPos.y - rBall <= 0) then VerDir := true;
if VerDir and (BallPos.y + rBall >= ClientRect.bottom) then VerDir := false;
{Calculate new ball position}
if HorDir then inc (BallPos.x, Dist) else dec (BallPos.x, Dist);
if VerDir then inc (BallPos.y, Dist) else dec (BallPos.y, Dist);
end;
DC := GetDC(HWindow);
{Now we prepare all in BG2DC}
{We erase the ball in the old position}
BitBlt (BG2DC, OldPos.x - rBall, OldPos.y - rBall, 2 * rBall, 2 * rBall,
BG1DC, OldPos.x - rBall, OldPos.y - rBall, SrcCopy);
{We or with the BallOrDC}
BitBlt (BG2DC, BallPos.x - rBall, BallPos.y - rBall, 2 * rBall, 2 * rBall,
BallOrDC, 0, 0, SrcPaint);
{We and with the BallAndDC}
BitBlt (BG2DC, BallPos.x - rBall, BallPos.y - rBall, 2 * rBall, 2 * rBall,
BallAndDC, 0, 0, SrcAnd);
{For optimized speed we calculate the rectangle to be updated on screen}
if BallPos.x > OldPos.x then
begin
x1 := OldPos.x - rBall;
x2 := BallPos.x + rBall;
end
else
begin
x1 := BallPos.x - rBall;
x2 := OldPos.x + rBall;
end;
if BallPos.y > OldPos.y then
begin
y1 := OldPos.y - rBall;
y2 := BallPos.y + rBall;
end
else
begin
y1 := BallPos.y - rBall;
y2 := OldPos.y + rBall;
end;
{And update the region including the old and the new ball position}
BitBlt (DC, x1, y1, x2 - x1, y2 - y1, BG2DC, x1, y1, SrcCopy);
ReleaseDC (hWindow, DC);
end;
procedure TApp.InitMainWindow;
begin
MainWindow := New (PMainWindow, Init (nil, 'Animate'));
end;
function tApp.IdleAction: boolean;
begin
pMainWindow (MainWindow)^.UpdateBall;
IdleAction := true;
end;
var
App: TApp;
begin
App.Init ('Animate');
App.Run;
App.Done;
end.