/*_______________________________________________________________ tc-011.c Function: This program demonstrates high speed frame animation of a hovering hummingbird. The software takes the format of a scientific presentation graphic. Compatibility: Supports all graphics adapters and monitors. The software uses the 640x200 16-color mode if a VGA or an EGA is present. The 640x200 2-color mode is used if a CGA is present. Remarks: The speed of the microprocessor has a dramatic effect upon the required animation speed. The current delay loops in the animation routines are suited for a standard 8088 CPU running at 4.77 MHz as found on an IBM PC. If your personal computer runs faster, you may wish to add longer delays in the animation routines. Refer to the book. Copyright 1988 Lee Adams and TAB BOOKS Inc. _________________________________________________________________ I N C L U D E F I L E S */ #include /* supports the printf function */ #include /* supports the graphics functions */ #include /* supports the exit() function */ #include /* supports memory moves */ #include /* supports read of keyboard buffer */ /*_______________________________________________________________ D E C L A R A T I O N S */ void keyboard(void);void quit_pgm(void); void notice(float x,float y);void coords(void); void graphics_setup(void);void labels(void);void draw_bird(void); void animVGAEGA(void); /* EGA and VGA only */ void animCGA(void); /* CGA only */ void pagemove(unsigned source,unsigned target); /* CGA only */ int frame=0,t1=1,t2=2; float sx,sy,sx1,sy1,sx2,sy2;float x_res,y_res; int C0=0,C1=1,C2=2,C3=3,C4=4,C5=5,C6=6,C7=7,C8=8,C9=9,C10=10, C11=11,C12=12,C13=13,C14=14,C15=15,mode_flag=0; char fill_75[]={187,238,187,238,187,238,187,238}; int p1=0; /* pointer into arrays */ int array1[][2]={ /* xy coordinates for body */ 205,219, 208,218, 212,214, 218,212, 221,208, 229,197, 232,192, 241,187, 250,183, 258,183, 265,185, 273,189, 282,198, 377,180, 376,182, 310,200, 297,207, 289,211, 286,217, 282,221, 278,230, 269,238, 256,248, 249,253, 240,261, 235,269, 231,278, 228,280, 214,294, 199,304, 188,310, 181,317, 177,324, 176,321, 169,328, 168,325, 162,330, 162,326, 135,340, 126,345, 120,345, 111,346, 106,349, 58,390, 49,399, 42,405, 42,402, 51,391, 74,364, 87,353, 99,339, 107,324, 114,309, 127,289, 138,274, 146,259}; int array2[][2]={ /* xy coordinates for near wing, frame 0 */ 146,259, 143,246, 136,234, 128,221, 110,199, 98,184, 88,169, 79,144, 76,136, 74,118, 73, 98, 69, 72, 74, 69, 80, 71, 86, 74, 107,101, 119,112, 124,118, 143,139, 154,154, 161,166, 166,171, 181,188, 187,195, 193,200, 197,209, 205,219, 179,259}; int array3[][2]={ /* xy coordinates for far wing, frame 0 */ 119,112, 118, 99, 118, 87, 121, 59, 121, 52, 126, 49, 134, 47, 139, 62, 146, 73, 154, 88, 174,129, 187,170, 194,184, 199,197, 207,209, 212,214, 139, 99}; int array4[][2]={ /* xy coordinates for eye */ 248,199, 250,196, 258,195, 261,197, 263,200, 261,204, 258,207, 252,205, 250,203, 248,199, 257,200}; int array5[][2]={ /* xy coordinates for throat markings */ 212,214, 218,212, 224,212, 222,217, 239,217, 237,219, 245,222, 259,219, 258,222, 269,220, 268,224, 278,220, 278,224, 282,221, 278,230, 269,238, 256,248, 249,253, 240,261, 240,258, 234,261, 234,257, 232,258, 232,253, 226,252, 227,249, 219,248, 222,244, 219,242, 220,240, 211,238, 214,230, 211,228, 212,214, 239,239}; int array6[][2]={ /* xy coordinates for near wing, frame 1 */ 146,259, 140,250, 129,245, 109,234, 92,219, 82,209, 77,193, 73,179, 74,159, 78,146, 84,136, 96,138, 119,147, 129,157, 140,165, 152,178, 159,184, 175,199, 189,210, 194,213, 205,219, 85,179}; int array7[][2]={ /* xy coordinates for far wing, frame 1 */ 152,178, 151,156, 151,137, 154,121, 156,113, 164, 98, 166, 89, 170, 84, 178, 93, 180,100, 185,107, 188,127, 191,148, 193,169, 197,179, 202,199, 212,214, 177,119}; int array8[][2]={ /* xy coordinates for near wing, frame 2 */ 146,259, 119,258, 104,253, 98,249, 93,241, 90,237, 90,228, 94,204, 97,198, 106,193, 124,190, 137,189, 151,195, 163,199, 175,208, 205,219, 109,242}; int array9[][2]={ /* xy coordinates for far wing, frame 2 */ 163,199, 163,184, 169,171, 169,152, 173,144, 178,138, 187,127, 194,119, 199,118, 202,125, 203,134, 204,162, 207,179, 209,195, 210,207, 212,214, 199,139}; int array10[][2]={ /* xy coordinates for near wing, frame 3 */ 146,259, 137,270, 124,277, 118,277, 114,276, 111,269, 112,260, 114,258, 125,246, 127,237, 139,228, 163,219, 174,218, 179,218, 191,219, 205,219, 119,269}; int array11[][2]={ /* xy coordinates for far wing, frame 3 */ 174,218, 178,203, 185,185, 192,177, 199,169, 211,160, 224,157, 227,161, 227,169, 226,177, 224,188, 217,205, 212,214, 219,179}; /*_______________________________________________________________ M A I N R O U T I N E */ main(){ graphics_setup(); /* establish graphics mode */ setcolor(C7); if (mode_flag==3) {setvisualpage(0);setactivepage(0);}; cleardevice(); frame=0; /* set the frame flag */ labels(); /* create the alphanumeric labels */ draw_bird(); /* draw the graphics */ if (mode_flag==4) {pagemove(0xB800,0x8800);} /* if CGA */ if (mode_flag==3) {setvisualpage(1);setactivepage(1);}; cleardevice(); frame=1; /* set the frame flag */ labels(); /* create the alphanumeric labels */ draw_bird(); /* draw the graphics */ if (mode_flag==4) {pagemove(0xB800,0x8C00);} /* if CGA */ if (mode_flag==3) {setvisualpage(2);setactivepage(2);}; cleardevice(); frame=2; /* set the frame flag */ labels(); /* create the alphanumeric labels */ draw_bird(); /* draw the graphics */ if (mode_flag==4) {pagemove(0xB800,0x9000);} /* if CGA */ if (mode_flag==3) {setvisualpage(3);setactivepage(3);}; cleardevice(); frame=3; /* set the frame flag */ labels(); /* create the alphanumeric labels */ draw_bird(); /* draw the graphics */ if (mode_flag==4) {pagemove(0xB800,0x9400);}; /* if CGA */ if (mode_flag==3) {setvisualpage(0);setactivepage(0);}; if (mode_flag==4) {pagemove(0x8800,0xB800);}; for (t1=1;t1<=30000;t1++); /* pause before animating */ if (mode_flag==3) animVGAEGA(); /* animation for VGA and EGA */ if (mode_flag==4) animCGA(); /* animation for CGA */ quit_pgm();} /* end the program gracefully */ /*_______________________________________________________________ SUBROUTINE: frame animation manager for VGA and EGA */ void animVGAEGA(void){ for (t1=1;t1!=2; ){ /* animate for endless loop */ setvisualpage(1);for (t2=1;t2<=1000;t2++); setvisualpage(2);for (t2=1;t2<=1000;t2++); setvisualpage(3);for (t2=1;t2<=1000;t2++);keyboard(); setvisualpage(2);for (t2=1;t2<=1000;t2++); setvisualpage(1);for (t2=1;t2<=1000;t2++); setvisualpage(0);for (t2=1;t2<=1000;t2++);keyboard();}; return;} /*_______________________________________________________________ SUBROUTINE: frame animation manager for CGA */ void animCGA(void){ for (t1=1;t1!=2; ){ /* animate for endless loop */ pagemove(0x8C00,0xB800);for (t2=1;t2<=1000;t2++); pagemove(0x9000,0xB800);for (t2=1;t2<=1000;t2++); pagemove(0x9400,0xB800);for (t2=1;t2<=1000;t2++);keyboard(); pagemove(0x9000,0xB800);for (t2=1;t2<=1000;t2++); pagemove(0x8C00,0xB800);for (t2=1;t2<=1000;t2++); pagemove(0x8800,0xB800);for (t2=1;t2<=1000;t2++);keyboard();}; return;} /*_______________________________________________________________ SUBROUTINE: pagemove for CGA This subroutine flips a graphics page from the screen buffer into RAM or from RAM to the screen buffer. */ void pagemove(unsigned source, unsigned target){ movedata(source,0x0000,target,0x0000,16000);return;} /*_______________________________________________________________ SUBROUTINE: display the alphanumeric labels */ void labels(void){ setcolor(C7);moveto(0,192); if (mode_flag==3) {outtext("640x200 16-color VGA and EGA mode");} if (mode_flag==4) {outtext("640x200 2-color CGA mode");} moveto(168,0); outtext("USING C FOR HIGH SPEED FRAME ANIMATION"); moveto(408,192);outtext("Press any key to quit."); setcolor(C14);moveto(424,40); outtext("Ruby-throated Hummingbird"); setcolor(C7); moveto(440,56); outtext("(Archilochus colubris)"); moveto(408,88); outtext("Range: Central & eastern U.S."); moveto(408,104);outtext("Breeds from southern"); moveto(408,112);outtext("Canada to the Gulf Coast."); moveto(408,128);outtext("Depicted here in its"); moveto(408,136);outtext("characteristic hovering"); moveto(408,144);outtext("flight pattern."); setcolor(C12); moveto(408,160);outtext("Animation rate:"); setcolor(C7); moveto(408,168); if (mode_flag==3) {outtext(" 36 frames per second.");} if (mode_flag==4) {outtext(" 10 frames per second.");} return;} /*_______________________________________________________________ SUBROUTINE: draw the graphics */ void draw_bird(void){ setcolor(C7);setfillstyle(SOLID_FILL,C7); sx=0;sy=30;coords();sx1=sx;sy1=sy; sx=385;sy=458;coords();sx2=sx;sy2=sy; bar(sx1,sy1,sx2,sy2); setcolor(C0); p1=0; /* draw the hummingbird's body */ sx=array1[p1][0];sy=array1[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=55;t1++){ sx=array1[p1][0];sy=array1[p1][1];p1++; coords();lineto(sx,sy);}; if (frame==0) { p1=0; /* draw near wings for frame 0 */ sx=array2[p1][0];sy=array2[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=26;t1++){ sx=array2[p1][0];sy=array2[p1][1];p1++; coords();lineto(sx,sy);}; sx=array2[p1][0];sy=array2[p1][1];coords(); p1=0; sx=array3[p1][0];sy=array3[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=15;t1++){ sx=array3[p1][0];sy=array3[p1][1];p1++; coords();lineto(sx,sy);}; sx=array3[p1][0];sy=array3[p1][1];coords(); } if (frame==1) { p1=0; /* draw near wings for frame 1 */ sx=array6[p1][0];sy=array6[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=20;t1++){ sx=array6[p1][0];sy=array6[p1][1];p1++; coords();lineto(sx,sy);}; sx=array6[p1][0];sy=array6[p1][1];coords(); p1=0; sx=array7[p1][0];sy=array7[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=16;t1++){ sx=array7[p1][0];sy=array7[p1][1];p1++; coords();lineto(sx,sy);}; sx=array7[p1][0];sy=array7[p1][1];coords(); } if (frame==2) { p1=0; /* draw near wings for frame 2 */ sx=array8[p1][0];sy=array8[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=15;t1++){ sx=array8[p1][0];sy=array8[p1][1];p1++; coords();lineto(sx,sy);}; sx=array8[p1][0];sy=array8[p1][1];coords(); p1=0; sx=array9[p1][0];sy=array9[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=15;t1++){ sx=array9[p1][0];sy=array9[p1][1];p1++; coords();lineto(sx,sy);}; sx=array9[p1][0];sy=array9[p1][1];coords(); } if (frame==3) { p1=0; /* draw near wings for frame 3 */ sx=array10[p1][0];sy=array10[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=15;t1++){ sx=array10[p1][0];sy=array10[p1][1];p1++; coords();lineto(sx,sy);}; sx=array10[p1][0];sy=array10[p1][1];coords(); p1=0; sx=array11[p1][0];sy=array11[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=12;t1++){ sx=array11[p1][0];sy=array11[p1][1];p1++; coords();lineto(sx,sy);}; sx=array11[p1][0];sy=array11[p1][1];coords(); } setcolor(C0); p1=0; /* draw the hummingbird's eye */ sx=array4[p1][0];sy=array4[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=9;t1++){ sx=array4[p1][0];sy=array4[p1][1];p1++; coords();lineto(sx,sy);}; sx=array4[p1][0];sy=array4[p1][1];coords(); setfillstyle(SOLID_FILL,C0);floodfill(sx,sy,C0); setcolor(C4);setfillstyle(SOLID_FILL,C4); p1=0; /* draw the throat markings */ sx=array5[p1][0];sy=array5[p1][1];p1++;coords();moveto(sx,sy); for (t1=1;t1<=33;t1++){ sx=array5[p1][0];sy=array5[p1][1];p1++; coords();lineto(sx,sy);}; sx=array5[p1][0];sy=array5[p1][1];coords();floodfill(sx,sy,C4); setcolor(C0);sx=5;sy=436;coords();notice(sx,sy); /* notice */ setcolor(C7);return;} /*_______________________________________________________________ SUBROUTINE: press any key to quit */ void keyboard(void){ if (bioskey(1)==0) return; else quit_pgm();} /*_______________________________________________________________ SUBROUTINE: GRACEFUL EXIT FROM THE PROGRAM */ void quit_pgm(void){ if (mode_flag==3) {setvisualpage(0);setactivepage(0);}; cleardevice();restorecrtmode();exit(0);} /*______________________________________________________________ SUBROUTINE: VGA/EGA/CGA/MCGA compatibility module */ void graphics_setup(void){ int graphics_adapter,graphics_mode; detectgraph(&graphics_adapter,&graphics_mode); if (graphics_adapter==VGA) goto VGA_EGA_mode; /* if VGA */ if (graphics_mode==EGAHI) goto VGA_EGA_mode; /* if EGA and ECD */ if (graphics_mode==EGALO) goto VGA_EGA_mode; /* if EGA and SCD */ if (graphics_adapter==CGA) goto CGA_mode; /* if CGA */ if (graphics_adapter==MCGA) goto CGA_mode; /* if MCGA */ goto abort_message; /* if no VGA, EGA, CGA, or MCGA */ VGA_EGA_mode: /* establish 640x200 16-color mode */ graphics_adapter=EGA;graphics_mode=EGALO; initgraph(&graphics_adapter,&graphics_mode,""); x_res=640;y_res=200;mode_flag=3; return; CGA_mode: /* establish 640x200 2-color mode */ graphics_adapter=CGA;graphics_mode=CGAHI; initgraph(&graphics_adapter,&graphics_mode,""); x_res=640;y_res=200;mode_flag=4; C0=0;C1=1;C2=1;C3=1;C4=0;C5=1,C6=1;C7=1; C8=1;C9=1;C10=1;C11=1;C12=1;C13=1;C14=1;C15=1; return; abort_message: printf("\n\nUnable to proceed.\n"); printf("Requires VGA, EGA, MCGA, or CGA adapter\n"); printf(" with appropriate monitor.\n"); printf("Please refer to the book.\n\n"); exit(0); } /*_______________________________________________________________ SUBROUTINE: coords() This subroutine accepts sx,sy device-independent display coordinates and returns sx,sy device-dependent screen coordinates scaled to fit the 640x480, 640x350, 640x200, or 320x200 screen, depending upon the graphics mode being used. */ void coords(void){ sx=sx*(x_res/640);sy=sy*(y_res/480);return;} /*_______________________________________________________________ SUBROUTINE: Copyright Notice This subroutine displays the standard copyright notice. If you are typing in this program from the book you can safely omit this subroutine, provided that you also remove the instruction "notice()" from the main routine. */ int copyright[][3]={0x7c00,0x0000,0x0000,0x8231, 0x819c,0x645e,0xba4a,0x4252,0x96d0,0xa231,0x8252,0x955e,0xba4a, 0x43d2,0xf442,0x8231,0x825c,0x945e,0x7c00,0x0000,0x0000}; void notice(float x, float y){ int a,b,c; int t1=0; for (t1=0;t1<=6;t1++){a=copyright[t1][0];b=copyright[t1][1]; c=copyright[t1][2]; setlinestyle(USERBIT_LINE,a,NORM_WIDTH); moveto(x,y);lineto(x+15,y); setlinestyle(USERBIT_LINE,b,NORM_WIDTH); moveto(x+16,y);lineto(x+31,y); setlinestyle(USERBIT_LINE,c,NORM_WIDTH); moveto(x+32,y);lineto(x+47,y);y=y+1;}; setlinestyle(USERBIT_LINE,0xFFFF,NORM_WIDTH); return;} /*_______________________________________________________________ End of source code */