home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 12
/
CD_ASCQ_12_0294.iso
/
maj
/
4401
/
manuals.arj
/
USER12.DOC
< prev
next >
Wrap
Text File
|
1994-01-24
|
26KB
|
629 lines
Chapter 12
Animation Techniques
238 Fastgraph User's Guide
Overview
Unlike other microcomputers, the IBM PC and PS/2 family of systems do
not have any special graphics hardware or firmware to help in performing
animation. This means that any animation done on these systems must be
implemented entirely through software. This chapter will show how to do this
using Fastgraph's video page management, image display, and block transfer
routines. The methods described in this chapter are not intended to be all
inclusive, for that would itself fill a separate volume at least as large as
this manual. However, the animation techniques presented here should provide
a basis that you can readily extend to develop more sophisticated uses of
animation. The examples in this chapter are restricted to graphics video
modes.
Simple Animation
The first type of animation we'll examine is called simple animation.
In simple animation, we display an object, erase it, and then display it in a
new position. When we perform this "erase and redisplay" sequence
repetitively, the object moves. This method, however, has two drawbacks.
First, unless the object is rather small, it will flicker because the erasing
and display of the object does not coincide with the refresh rate of the
video display. Second, and perhaps more importantly, anything underneath the
object is not saved as the object moves across it. Despite these
limitations, simple animation is sometimes useful, and it is a good place to
begin our discussion of animation techniques.
Example 12-1 moves a small bright green rectangle (magenta in CGA) from
left to right across the screen in any 320 by 200 color graphics mode. The
program moves the rectangle, 20 pixels wide and 10 pixels high, using a for
loop. This loop first uses the fg_clprect routine to display the rectangle,
then uses the fg_waitfor routine to leave the object on the screen
momentarily, and finally uses fg_clprect again to erase the rectangle by
redisplaying it in the original background color (the fg_waitfor routine is
described in Chapter 16). We use fg_clprect rather than fg_rect because the
first few and last few loop iterations result in at least part of the
rectangle being off the screen. Each successive loop iteration displays the
rectangle five pixels to the right of its previous position.
Example 12-1.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
int new_mode, old_mode;
int x;
/* initialize the video environment */
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
Chapter 12: Animation Techniques 239
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
/* move the object across the screen */
for (x = -20; x < 320; x+=5) {
fg_setcolor(10);
fg_clprect(x,x+19,95,104);
fg_waitfor(1);
fg_setcolor(0);
fg_clprect(x,x+19,95,104);
}
/* restore the original video mode and return to DOS */
fg_setmode(old_mode);
fg_reset();
}
Example 12-2 is the same as example 12-1, but it shows what happens when
we move the rectangle across an existing background (in this case, the
background is solid white). If you run this program, you'll see that the
rectangle leaves a trail of color 0 behind it. While this might be
occasionally useful, it demonstrates that simple animation is destructive
because it does not preserve the background. In this example, if we changed
the second call to fg_setcolor within the for loop to revert to color 15
instead of color 0, the background would be restored. In general, though, it
may not be this easy to replace the background, so we must rely on some other
method for preserving it.
Example 12-2.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
int new_mode, old_mode;
int x;
/* initialize the video environment */
new_mode = fg_bestmode(320,200,1);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
240 Fastgraph User's Guide
/* draw some type of background */
fg_setcolor(15);
fg_rect(0,319,0,199);
/* move the object across the screen */
for (x = -20; x < 320; x+=5) {
fg_setcolor(10);
fg_clprect(x,x+19,95,104);
fg_waitfor(1);
fg_setcolor(0);
fg_clprect(x,x+19,95,104);
}
/* restore the original video mode and return to DOS */
fg_setmode(old_mode);
fg_reset();
}
To summarize, we see that simple animation is easy to implement, but it
is destructive and typically causes the animated object to flicker. For
these reasons, it is not used too frequently.
XOR Animation
"Exclusive or" animation, or XOR animation for short, is an interesting
extension of simple animation and is most useful when animating a single-
color object against a single-color background. Like simple animation, it
uses the "erase and redisplay" technique to move an object, but it does this
differently. Instead of erasing the object by displaying it in the
background color, XOR animation does so by displaying it in the same color
using an exclusive or, or XOR, operation. This method relies on a specific
property of the exclusive or operator:
(object XOR background) XOR object = background
In other words, if you XOR something twice in the same position, the result
is the same as the original image in that position.
Example 12-3 demonstrates XOR animation. This program is similar to
example 12-2, but it only runs in the 320 by 200 EGA graphics mode (mode 13).
After establishing the video mode, it uses the Fastgraph routine fg_setfunc
to select XOR mode. This causes any subsequent graphics output to be XORed
with the contents of video memory instead of just replacing it. The
fg_setfunc routine is described further in Chapter 17.
The other differences between examples 12-3 and 12-2 are that the call
to fg_setcolor has been moved outside the for loop, and that fg_setcolor
takes a different value. Since the existing background is bright white
(color 15), we can't just use color 10 if we want to display a bright green
object. The desired value is that which when XORed with color 15 produces
color 10; the easiest way to obtain this value is to XOR these two numbers.
Chapter 12: Animation Techniques 241
The call to fg_setcolor can be moved outside the loop because we display the
object using the same color index throughout.
Example 12-3.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
int old_mode;
int x;
/* initialize the video environment */
if (fg_testmode(13,1) == 0) {
printf("This program requires EGA.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(13);
fg_setfunc(3);
/* draw some type of background */
fg_setcolor(15);
fg_rect(0,319,0,199);
/* move the object across the screen */
fg_setcolor(10^15);
for (x = -20; x < 320; x+=5) {
fg_clprect(x,x+19,95,104);
fg_waitfor(1);
fg_clprect(x,x+19,95,104);
}
/* restore the original video mode and return to DOS */
fg_setmode(old_mode);
fg_reset();
}
Fastgraph only supports the XOR pixel operation in the native EGA and
VGA graphics video modes (modes 13 through 18). Thus, you cannot use XOR
animation in CGA, Tandy/PCjr, Hercules, or MCGA graphics modes.
While XOR animation is non-destructive (that is, it restores the
original background), it still suffers from the flickering encountered in
simple animation. In spite of this, it may be useful when animating a
single-color object against a single-color background.
242 Fastgraph User's Guide
Static Frame Animation
Static frame animation uses a different strategy than simple animation
or XOR animation. The general scheme of this method is to create the entire
animation sequence off-screen and then successively display each item, or
frame, in this sequence on one position of the visual video page. This
results in a visually appealing animation that is non-destructive and does
not include the flickering associated with simple animation and XOR
animation. Static frame animation requires the visual video page and one or
more additional pages to implement. The number of pages needed depends on
the number of frames and the size of each frame.
Example 12-4 runs in any 320 by 200 color graphics video mode and
illustrates a simple use of static frame animation. The program displays an
animation sequence containing 12 frames; it displays this sequence three
times. The animation sequence consists of a bright green rectangle (magenta
in CGA) moving from left to right across the center of the frame. Each frame
is 96 pixels wide and 50 pixels high. The 12 frames are set up on an off-
screen video page as shown below.
0 95 96 191 192 287
0
frame 1 frame 2 frame 3
49
50
frame 4 frame 5 frame 6
99
100
frame 7 frame 8 frame 9
149
150
frame 10 frame 11 frame 12
199
Example 12-4 first establishes the video mode and allocates the
additional video page (needed if using a video mode in which page 1 is a
virtual video page). The program then generates the background for frame 1;
the background is a blue rectangle (cyan in CGA) with a white ellipse
centered on it. After the call to fg_ellipse, the first frame is ready.
The next step is to create the remaining 11 frames. In frame 2, the
right half of the 20-pixel wide rectangle will enter the left edge of the
frame. In frame 3, the rectangle will be ten pixels farther right, or
aligned against the left edge of the frame. In frames 4 through 12, the
rectangle will be ten pixels farther right in each frame, so by frame 12 only
the left half of the rectangle appears on the right edge of the frame. The
first for loop in the program builds frames 2 through 12 by copying the
background from frame 1 and then displaying the rectangle (that is, the
animated object) in the proper position for that frame.
Chapter 12: Animation Techniques 243
The second for loop performs the animation sequence. To display the 12-
frame sequence three times, it must perform 36 iterations. The loop simply
copies each frame from the proper position on video page 1 to the middle of
the visual video page. Note how the fg_waitfor routine is used to pause
momentarily between each frame.
Example 12-4.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
#define VISUAL 0
#define HIDDEN 1
int xmin[] = { 0, 96,192, 0, 96,192, 0, 96,192, 0, 96,192};
int ymax[] = { 49, 49, 49, 99, 99, 99,149,149,149,199,199,199};
void main()
{
int new_mode, old_mode;
int frame, offset;
int i, x, y;
/* initialize the video environment */
new_mode = fg_bestmode(320,200,2);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_allocate(HIDDEN);
/* draw the background in the upper left corner */
fg_setpage(HIDDEN);
fg_setcolor(1);
fg_rect(0,95,0,49);
fg_setcolor(15);
fg_move(48,25);
fg_ellipse(20,20);
/* display the animated object against each background */
fg_setcolor(10);
offset = -10;
for (i = 1; i < 12; i++) {
x = xmin[i];
y = ymax[i];
fg_transfer(0,95,0,49,x,y,HIDDEN,HIDDEN);
fg_setclip(x,x+95,0,199);
fg_clprect(x+offset,x+offset+19,y-29,y-20);
offset += 10;
244 Fastgraph User's Guide
}
/* slide the object across the background three times */
for (i = 0; i < 36; i++) {
frame = i % 12;
x = xmin[frame];
y = ymax[frame];
fg_transfer(x,x+95,y-49,y,112,124,HIDDEN,VISUAL);
fg_waitfor(2);
}
/* restore the original video mode and return to DOS */
fg_freepage(HIDDEN);
fg_setmode(old_mode);
fg_reset();
}
Dynamic Frame Animation
Dynamic frame animation is similar to static frame animation, but all
the animation frames are built as needed during the animation sequence
instead of in advance. When using this method, you must first store a copy
of the background on an off-screen video page. Then, to build a frame,
create another copy (called the workspace) of the background elsewhere on the
off-screen page (or even to a different off-screen page) and display the
object on that copy. Finally, transfer the workspace to the visual page.
Like static frame animation, this method produces a non-destructive, flicker-
free animation sequence.
Example 12-5 is functionally identical to example 12-4, but it uses
dynamic rather than static frame animation. As before, the program builds
the background in the upper left corner of video page 1, but it then uses
fg_transfer to copy it to the center of the visual video page. The for loop
builds each frame as it is needed and also copies it to the center of the
visual page. Again, fg_waitfor creates the necessary pause between frames.
Example 12-5.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
#define VISUAL 0
#define HIDDEN 1
void main()
{
int new_mode, old_mode;
int frame, offset;
int i;
Chapter 12: Animation Techniques 245
/* initialize the video environment */
new_mode = fg_bestmode(320,200,2);
if (new_mode < 0 || new_mode == 12) {
printf("This program requires a 320 ");
printf("x 200 color graphics mode.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(new_mode);
fg_allocate(HIDDEN);
/* draw the background in the upper left corner */
fg_setpage(HIDDEN);
fg_setcolor(1);
fg_rect(0,95,0,49);
fg_setcolor(15);
fg_move(48,25);
fg_ellipse(20,20);
/* copy it to the center of the visual page */
fg_transfer(0,95,0,49,112,124,HIDDEN,VISUAL);
/* slide the object across the background three times */
fg_setcolor(10);
for (i = 0; i < 36; i++) {
frame = i % 12;
offset = 10 * frame - 10;
fg_transfer(0,95,20,29,112,105,HIDDEN,HIDDEN);
fg_rect(112+offset,131+offset,96,105);
fg_transfer(112,207,96,105,112,105,HIDDEN,VISUAL);
fg_waitfor(2);
}
/* restore the original video mode and return to DOS */
fg_freepage(HIDDEN);
fg_setmode(old_mode);
fg_reset();
}
Two items in example 12-5 merit further discussion. First, we have
chosen our workspace on page 1 so it uses the same screen space coordinates
as the image area on the visual page. This is not necessary unless you are
using the fg_restore routine instead of fg_transfer. Second, the program can
use the faster fg_rect routine in place of fg_clprect. It can do this
because even though the object will extend beyond the workspace limits, we
only transfer the workspace itself. However, for this to function properly,
the workspace's horizontal limits must fall on byte boundaries.
Note too that we do not need to transfer the entire frame during the
animation sequence. In example 12-5, we know the vertical extremes of the
moving image are y=96 and y=105, so we only transfer 10 rows instead of the
246 Fastgraph User's Guide
entire frame. We could similarly compute the x extremes for each frame and
only transfer the necessary portion. Recall, however, that fg_transfer
extends the horizontal coordinates to byte boundaries, so we may copy a few
extra pixels as well. This may or may not affect the animation sequence.
Again, the problem is eliminated if you align your workspace on byte
boundaries.
When we use dynamic frame animation, it is easy to change the number of
frames in the animation sequence. Suppose we wish to produce a smoother
animation by increasing the number of frames from 12 to 24. This means the
object will move in increments of five pixels instead of ten. The only
changes needed are to double the number of loop iterations, modify the
calculations for the frame number and offset values as shown below, and
reduce the fg_waitfor pause from 2 to 1.
frame = i % 24;
offset = 5 * frame - 10;
Compare this to all the changes that would be necessary if we were using
static frame animation.
Page Flipping
Page flipping is a variation of frame animation in which you construct
images on off-screen video pages and then repetitively make those pages the
visual page. We can further divide the page flipping technique into static
and dynamic variants, as we did with frame animation.
In static page flipping, we construct the entire animation sequence in
advance, with one frame per video page. Once this is done, we can display
each frame by using the fg_setvpage routine to switch instantly from one
video page to another. Although this produces a smooth, flicker-free
animation, we cannot carry the sequence very far before running out of video
pages (and hence animation frames).
In dynamic page flipping, we construct each animation frame when it is
needed. As in static page flipping, we construct each frame on a separate
video page. However, as example 12-6 demonstrates, we only need three video
pages to produce the animation sequence, regardless of the number of frames
in the sequence. Two of the three video pages will alternate as the visual
page, while the remaining video page keeps a copy of the background.
Example 12-6, which performs an animation sequence similar to examples
12-4 and 12-5, illustrates dynamic frame animation in the 320 by 200 EGA
graphics video mode (mode 13). The program begins by displaying the
background on video page 2. Video pages 0 and 1 will alternate as the visual
page; the page that is not the visual page is called the hidden page. We
start with page 0 as the visual page, and hence page 1 as the hidden page.
To build each frame, the program uses fg_transfer to copy the background from
page 2 to the hidden page and then uses fg_clprect to display the animated
object at the correct position on the hidden page. After this, it displays
the next frame by using fg_setvpage to make the hidden page the visual page.
Before beginning the next iteration, the program toggles the hidden page
number in preparation for the next frame.
Chapter 12: Animation Techniques 247
Example 12-6.
#include <fastgraf.h>
#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
int old_mode;
int hidden;
int x;
/* initialize the video environment */
if (testmode(fg_13,3) == 0) {
printf("This program requires EGA.\n");
exit(1);
}
old_mode = fg_getmode();
fg_setmode(13);
/* draw the background on page two */
fg_setpage(2);
fg_setcolor(1);
fg_rect(0,319,0,199);
fg_setcolor(15);
fg_move(160,100);
fg_ellipse(20,20);
/* slide the object across the screen */
hidden = 1;
setcolor(10);
for (x = -10; x < 320; x+=4) {
fg_setpage(hidden);
fg_transfer(0,319,0,199,0,199,2,hidden);
fg_clprect(x,x+19,96,105);
fg_setvpage(hidden);
hidden = 1 - hidden;
fg_waitfor(1);
}
/* restore the original video mode and return to DOS */
fg_setmode(old_mode);
fg_reset();
}
A problem with either page flipping technique arises if we use virtual
video pages. Page flipping relies on the fact that changing the visual page
number occurs instantly, which is exactly what happens when we use physical
video pages. However, such is not the case with virtual or logical pages
because Fastgraph must copy the entire page contents into video memory.
248 Fastgraph User's Guide
While this occurs quite rapidly, it is not instantaneous, and its effects are
immediately apparent on the animation.
An Animation Example: The Fastgraph Fish Tank
If you installed the example programs when you installed Fastgraph, the
EXAMPLES subdirectory will include a fully-commented program called the fish
tank that illustrates dynamic frame animation. The fish tank is an excellent
example of multi-object non-destructive animation in which several types of
tropical fish swim back and forth against a coral reef background. As a
picture is worth 1,024 words, we suggest studying the fish tank source code
for some useful techniques in developing a complete animation program. The
source code for the fish tank program is in FISHTANK.C, FISHTANK.BAS,
FISHTANK.FOR, or FISHTANK.PAS, depending on what language support you've
installed with Fastgraph.
Summary of Animation Techniques
This chapter has presented five animation techniques: simple animation,
XOR animation, static frame animation, dynamic frame animation, and page
flipping. The following table summarizes their behavior.
technique destructive? flicker-free?
simple yes no
XOR no no
static frame no yes
dynamic frame no yes
page flipping no yes
Simple animation and XOR animation are elementary techniques that are seldom
used once you master frame animation and page flipping.
As stated at the beginning of this chapter, the simple examples
presented here serve as the basis for understanding the mechanics of the
animation techniques we have discussed. In "real world" programs, you'll
typically want to display an image using the fg_drwimage or fg_drawmap family
of routines instead using rudimentary images such as the rectangles in our
examples. A helpful rule is to use PCX, GIF, or pixel run files for both
backgrounds and moving objects, and then use fg_getimage or fg_getmap to
retrieve the moving objects as bit-mapped images for later display. Of
course, it's desirable to do this "behind the scenes" work on video pages
other than the visual page. This is precisely the technique used in the
Fastgraph fish tank.