INFO: An Efficient Animation AlgorithmID: Q75431
|
An application that shows an animated image cannot rely solely on Windows
graphical device interface (GDI) functions because they will be too slow.
Instead, the application must create its own set of bitmaps. This article
discusses the process required and provides tips to improve performance and
memory use.
This information applies to any type of animation or fast drawing, from
painting the game pieces in Reversi to updating the time each second in
Clock.
There are three major steps to this process:
X_SIZE = width of the cel
Y_SIZE = height of the cel
NUM_CELS = number of cels in the animated sequence
HBITMAP hbm;
hbm = CreateDiscardableBitmap(hDC, X_SIZE, NUM_CELS * Y_SIZE);
if (!hbm)
{
// error - could not allocate bitmap
}
if (hTmpDC = CreateCompatibleDC(hDC))
{
HBITMAP hOldBm;
hOldBm = SelectObject(hTmpDC, hbm);
// and so forth
}
In many cases, all cels will share the same background. Rather than drawing
this background several times onto the bitmap, draw it once onto the first
cel and copy it to the other cels, as the following code demonstrates:
// GDI calls to draw to hbm from (0, 0) to (X_SIZE, Y_SIZE)
for (i = 1; i < NUM_CELS; i++) // Perform the copy
BitBlt(hTmpDC, 0, i * Y_SIZE, X_SIZE, Y_SIZE, hTmpDC, 0, 0,
SRCCOPY);
After the background is copied, draw the foreground on each cel, using
regular GDI calls (in TRANSPARENT drawing mode). The coordinates for cel
"i" in bitmap hbm are:
x_pos: 0 to (X_SIZE - 1)
y_pos: (i * Y_SIZE) to (((i + 1) * Y_SIZE) - 1)
If the cels in the bitmap contain sequential images, animating to the
screen is simplified.
SelectObject(hTmpDC, hOldBm);
DeleteDC(hTmpDC);
if ((hTmpDC = CreateCompatibleDC(hDC)) != NULL)
{
HBITMAP hOldBm;
if (!(hOldBm = SelectObject(hTmpDC, hbm))
// must re-allocate bitmap. Note that this MAY FAIL!!!
At this point, call the BitBlt() function to copy the various stages of the animation sequence to the screen. If the cels in the bitmap contain
sequential images, a simple loop will do the job nicely, as the following
code demonstrates:
for (i = 0; i < NUM_CELS; i++)
{
BitBlt (hDC, x_pos, y_pos, X_SIZE, Y_SIZE, hTmpDC, 0,
i * Y_SIZE, SRCCOPY);
// Some form of delay goes here. A real-time wait, based on
// clock ticks, is recommended.
}
When the drawing is done, delete the temporary DC:
SelectObject(hTmpDC, hOldBm);
DeleteDC(hTmpDC);
It is important to cancel the selection of the bitmap between passes
through the for loop. This allows the bitmap to be discarded if the system
runs low on memory.
Additional query words: 3.00 3.10 3.50 4.00 animation win16sdk
Keywords : kbSDKWin32 kbWinOS310 kbWinOS95 kbDSupport kbWinOS300
Version : WINDOWS:3.0,3.1,95; winnt:3.5,3.51
Platform : WINDOWS winnt
Issue type : kbinfo
Last Reviewed: July 13, 1999