home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / source / chapter49 / l49-5.c < prev    next >
C/C++ Source or Header  |  1997-06-18  |  10KB  |  241 lines

  1. /* Sample mode X VGA animation program. Portions of this code first appeared 
  2. in PC Techniques. 
  3. Tested with Borland C++ 4.02 in small model by Jim Mischel 12/16/94.
  4. */
  5. #include <stdio.h>
  6. #include <conio.h>
  7. #include <dos.h>
  8. #include <math.h>
  9. #include "maskim.h"
  10.  
  11. #define SCREEN_SEG         0xA000
  12. #define SCREEN_WIDTH       320
  13. #define SCREEN_HEIGHT      240
  14. #define PAGE0_START_OFFSET 0
  15. #define PAGE1_START_OFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH)/4)
  16. #define BG_START_OFFSET    (((long)SCREEN_HEIGHT*SCREEN_WIDTH*2)/4)
  17. #define DOWNLOAD_START_OFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH*3)/4)
  18.  
  19. static unsigned int PageStartOffsets[2] =
  20.    {PAGE0_START_OFFSET,PAGE1_START_OFFSET};
  21. static char GreenAndBrownPattern[] =
  22.    {2,6,2,6, 6,2,6,2, 2,6,2,6, 6,2,6,2};
  23. static char PineTreePattern[] = {2,2,2,2, 2,6,2,6, 2,2,6,2, 2,2,2,2};
  24. static char BrickPattern[] = {6,6,7,6, 7,7,7,7, 7,6,6,6, 7,7,7,7,};
  25. static char RoofPattern[] = {8,8,8,7, 7,7,7,7, 8,8,8,7, 8,8,8,7};
  26.  
  27. #define SMOKE_WIDTH  7
  28. #define SMOKE_HEIGHT 7
  29. static char SmokePixels[] = {
  30.    0, 0,15,15,15, 0, 0,
  31.    0, 7, 7,15,15,15, 0,
  32.    8, 7, 7, 7,15,15,15,
  33.    8, 7, 7, 7, 7,15,15,
  34.    0, 8, 7, 7, 7, 7,15,
  35.    0, 0, 8, 7, 7, 7, 0,
  36.    0, 0, 0, 8, 8, 0, 0};
  37. static char SmokeMask[] = {
  38.    0, 0, 1, 1, 1, 0, 0,
  39.    0, 1, 1, 1, 1, 1, 0,
  40.    1, 1, 1, 1, 1, 1, 1,
  41.    1, 1, 1, 1, 1, 1, 1,
  42.    1, 1, 1, 1, 1, 1, 1,
  43.    0, 1, 1, 1, 1, 1, 0,
  44.    0, 0, 1, 1, 1, 0, 0};
  45. #define KITE_WIDTH  10
  46. #define KITE_HEIGHT 16
  47. static char KitePixels[] = {
  48.    0, 0, 0, 0,45, 0, 0, 0, 0, 0,
  49.    0, 0, 0,46,46,46, 0, 0, 0, 0,
  50.    0, 0,47,47,47,47,47, 0, 0, 0,
  51.    0,48,48,48,48,48,48,48, 0, 0,
  52.   49,49,49,49,49,49,49,49,49, 0,
  53.    0,50,50,50,50,50,50,50, 0, 0,
  54.    0,51,51,51,51,51,51,51, 0, 0,
  55.    0, 0,52,52,52,52,52, 0, 0, 0,
  56.    0, 0,53,53,53,53,53, 0, 0, 0,
  57.    0, 0, 0,54,54,54, 0, 0, 0, 0,
  58.    0, 0, 0,55,55,55, 0, 0, 0, 0,
  59.    0, 0, 0, 0,58, 0, 0, 0, 0, 0,
  60.    0, 0, 0, 0,59, 0, 0, 0, 0,66,
  61.    0, 0, 0, 0,60, 0, 0,64, 0,65,
  62.    0, 0, 0, 0, 0,61, 0, 0,64, 0,
  63.    0, 0, 0, 0, 0, 0,62,63, 0,64};
  64. static char KiteMask[] = {
  65.    0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
  66.    0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
  67.    0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
  68.    0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
  69.    1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
  70.    0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
  71.    0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
  72.    0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
  73.    0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
  74.    0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
  75.    0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
  76.    0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
  77.    0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
  78.    0, 0, 0, 0, 1, 0, 0, 1, 0, 1,
  79.    0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
  80.    0, 0, 0, 0, 0, 0, 1, 1, 0, 1};
  81. static MaskedImage KiteImage;
  82.  
  83. #define NUM_OBJECTS  20
  84. typedef struct {
  85.    int X,Y,Width,Height,XDir,YDir,XOtherPage,YOtherPage;
  86.    MaskedImage *Image;
  87. } AnimatedObject;
  88. AnimatedObject AnimatedObjects[] = {
  89.    {  0,  0,KITE_WIDTH,KITE_HEIGHT, 1, 1,  0,  0,&KiteImage},
  90.    { 10, 10,KITE_WIDTH,KITE_HEIGHT, 0, 1, 10, 10,&KiteImage},
  91.    { 20, 20,KITE_WIDTH,KITE_HEIGHT,-1, 1, 20, 20,&KiteImage},
  92.    { 30, 30,KITE_WIDTH,KITE_HEIGHT,-1,-1, 30, 30,&KiteImage},
  93.    { 40, 40,KITE_WIDTH,KITE_HEIGHT, 1,-1, 40, 40,&KiteImage},
  94.    { 50, 50,KITE_WIDTH,KITE_HEIGHT, 0,-1, 50, 50,&KiteImage},
  95.    { 60, 60,KITE_WIDTH,KITE_HEIGHT, 1, 0, 60, 60,&KiteImage},
  96.    { 70, 70,KITE_WIDTH,KITE_HEIGHT,-1, 0, 70, 70,&KiteImage},
  97.    { 80, 80,KITE_WIDTH,KITE_HEIGHT, 1, 2, 80, 80,&KiteImage},
  98.    { 90, 90,KITE_WIDTH,KITE_HEIGHT, 0, 2, 90, 90,&KiteImage},
  99.    {100,100,KITE_WIDTH,KITE_HEIGHT,-1, 2,100,100,&KiteImage},
  100.    {110,110,KITE_WIDTH,KITE_HEIGHT,-1,-2,110,110,&KiteImage},
  101.    {120,120,KITE_WIDTH,KITE_HEIGHT, 1,-2,120,120,&KiteImage},
  102.    {130,130,KITE_WIDTH,KITE_HEIGHT, 0,-2,130,130,&KiteImage},
  103.    {140,140,KITE_WIDTH,KITE_HEIGHT, 2, 0,140,140,&KiteImage},
  104.    {150,150,KITE_WIDTH,KITE_HEIGHT,-2, 0,150,150,&KiteImage},
  105.    {160,160,KITE_WIDTH,KITE_HEIGHT, 2, 2,160,160,&KiteImage},
  106.    {170,170,KITE_WIDTH,KITE_HEIGHT,-2, 2,170,170,&KiteImage},
  107.    {180,180,KITE_WIDTH,KITE_HEIGHT,-2,-2,180,180,&KiteImage},
  108.    {190,190,KITE_WIDTH,KITE_HEIGHT, 2,-2,190,190,&KiteImage},
  109. };
  110. void main(void);
  111. void DrawBackground(unsigned int);
  112. void MoveObject(AnimatedObject *);
  113. extern void Set320x240Mode(void);
  114. extern void FillRectangleX(int, int, int, int, unsigned int, int);
  115. extern void FillPatternX(int, int, int, int, unsigned int, char*);
  116. extern void CopySystemToScreenMaskedX(int, int, int, int, int, int,
  117.    char *, unsigned int, int, int, char *);
  118. extern void CopyScreenToScreenX(int, int, int, int, int, int,
  119.    unsigned int, unsigned int, int, int);
  120. extern unsigned int CreateAlignedMaskedImage(MaskedImage *,
  121.    unsigned int, char *, int, int, char *);
  122. extern void CopyScreenToScreenMaskedX(int, int, int, int, int, int,
  123.    MaskedImage *, unsigned int, int);
  124. extern void ShowPage(unsigned int);
  125.  
  126. void main()
  127. {
  128.    int DisplayedPage, NonDisplayedPage, Done, i;
  129.    union REGS regset;
  130.    Set320x240Mode();
  131.    /* Download the kite image for fast copying later */
  132.    if (CreateAlignedMaskedImage(&KiteImage, DOWNLOAD_START_OFFSET,
  133.          KitePixels, KITE_WIDTH, KITE_HEIGHT, KiteMask) == 0) {
  134.       regset.x.ax = 0x0003; int86(0x10, ®set, ®set);
  135.       printf("Couldn't get memory\n"); exit();
  136.    }
  137.    /* Draw the background to the background page */
  138.    DrawBackground(BG_START_OFFSET);
  139.    /* Copy the background to both displayable pages */
  140.    CopyScreenToScreenX(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0,
  141.          BG_START_OFFSET, PAGE0_START_OFFSET, SCREEN_WIDTH,
  142.          SCREEN_WIDTH);
  143.    CopyScreenToScreenX(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0,
  144.          BG_START_OFFSET, PAGE1_START_OFFSET, SCREEN_WIDTH,
  145.          SCREEN_WIDTH);
  146.    /* Move the objects and update their images in the nondisplayed
  147.       page, then flip the page, until Esc is pressed */
  148.    Done = DisplayedPage = 0;
  149.    do {
  150.       NonDisplayedPage = DisplayedPage ^ 1;
  151.       /* Erase each object in nondisplayed page by copying block from
  152.             background page at last location in that page */
  153.       for (i=0; i<NUM_OBJECTS; i++) {
  154.          CopyScreenToScreenX(AnimatedObjects[i].XOtherPage,
  155.                AnimatedObjects[i].YOtherPage,
  156.                AnimatedObjects[i].XOtherPage +
  157.                AnimatedObjects[i].Width,
  158.                AnimatedObjects[i].YOtherPage +
  159.                AnimatedObjects[i].Height,
  160.                AnimatedObjects[i].XOtherPage,
  161.                AnimatedObjects[i].YOtherPage, BG_START_OFFSET,
  162.                PageStartOffsets[NonDisplayedPage], SCREEN_WIDTH,
  163.                SCREEN_WIDTH);
  164.       }
  165.       /* Move and draw each object in the nondisplayed page */
  166.       for (i=0; i<NUM_OBJECTS; i++) {
  167.          MoveObject(&AnimatedObjects[i]);
  168.          /* Draw object into nondisplayed page at new location */
  169.          CopyScreenToScreenMaskedX(0, 0, AnimatedObjects[i].Width,
  170.                AnimatedObjects[i].Height, AnimatedObjects[i].X,
  171.                AnimatedObjects[i].Y, AnimatedObjects[i].Image,
  172.                PageStartOffsets[NonDisplayedPage], SCREEN_WIDTH);
  173.       }
  174.       /* Flip to the page into which we just drew */
  175.       ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
  176.       /* See if it's time to end */
  177.       if (kbhit()) {
  178.          if (getch() == 0x1B) Done = 1;   /* Esc to end */
  179.       }
  180.    } while (!Done);   
  181.    /* Restore text mode and done */
  182.    regset.x.ax = 0x0003; int86(0x10, ®set, ®set);
  183. }
  184. void DrawBackground(unsigned int PageStart)
  185. {
  186.    int i,j,Temp;
  187.    /* Fill the screen with cyan */
  188.    FillRectangleX(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, PageStart, 11);
  189.    /* Draw a green and brown rectangle to create a flat plain */
  190.    FillPatternX(0, 160, SCREEN_WIDTH, SCREEN_HEIGHT, PageStart,
  191.                                                       GreenAndBrownPattern);
  192.    /* Draw blue water at the bottom of the screen */
  193.    FillRectangleX(0, SCREEN_HEIGHT-30, SCREEN_WIDTH, SCREEN_HEIGHT,
  194.                                                                PageStart, 1);
  195.    /* Draw a brown mountain rising out of the plain */
  196.    for (i=0; i<120; i++)
  197.       FillRectangleX(SCREEN_WIDTH/2-30-i, 51+i, SCREEN_WIDTH/2-30+i+1,
  198.                                                       51+i+1, PageStart, 6);
  199.    /* Draw a yellow sun by overlapping rects of various shapes */
  200.    for (i=0; i<=20; i++) {
  201.       Temp = (int)(sqrt(20.0*20.0 - (float)i*(float)i) + 0.5);
  202.       FillRectangleX(SCREEN_WIDTH-25-i, 30-Temp, SCREEN_WIDTH-25+i+1,
  203.                                                   30+Temp+1, PageStart, 14);
  204.    }
  205.    /* Draw green trees down the side of the mountain */
  206.    for (i=10; i<90; i += 15)
  207.       for (j=0; j<20; j++)
  208.        FillPatternX(SCREEN_WIDTH/2+i-j/3-15, i+j+51,SCREEN_WIDTH/2+i+j/3-15+1, 
  209.                                        i+j+51+1, PageStart, PineTreePattern);
  210.    /* Draw a house on the plain */
  211.    FillPatternX(265, 150, 295, 170, PageStart, BrickPattern);
  212.    FillPatternX(265, 130, 270, 150, PageStart, BrickPattern);
  213.    for (i=0; i<12; i++)
  214.       FillPatternX(280-i*2, 138+i, 280+i*2+1, 138+i+1, PageStart, RoofPattern);
  215.    /* Finally, draw puffs of smoke rising from the chimney */
  216.    for (i=0; i<4; i++)
  217.       CopySystemToScreenMaskedX(0, 0, SMOKE_WIDTH, SMOKE_HEIGHT, 264,
  218.         110-i*20, SmokePixels, PageStart, SMOKE_WIDTH,SCREEN_WIDTH, SmokeMask);
  219. }
  220. /* Move the specified object, bouncing at the edges of the screen and
  221.    remembering where the object was before the move for erasing next time */
  222. void MoveObject(AnimatedObject * ObjectToMove) {
  223.    int X, Y;
  224.    X = ObjectToMove->X + ObjectToMove->XDir;
  225.    Y = ObjectToMove->Y + ObjectToMove->YDir;
  226.    if ((X < 0) || (X > (SCREEN_WIDTH - ObjectToMove->Width))) {
  227.       ObjectToMove->XDir = -ObjectToMove->XDir;
  228.       X = ObjectToMove->X + ObjectToMove->XDir;
  229.    }
  230.    if ((Y < 0) || (Y > (SCREEN_HEIGHT - ObjectToMove->Height))) {
  231.       ObjectToMove->YDir = -ObjectToMove->YDir;
  232.       Y = ObjectToMove->Y + ObjectToMove->YDir;
  233.    }
  234.    /* Remember previous location for erasing purposes */
  235.    ObjectToMove->XOtherPage = ObjectToMove->X;
  236.    ObjectToMove->YOtherPage = ObjectToMove->Y;
  237.    ObjectToMove->X = X; /* set new location */
  238.    ObjectToMove->Y = Y;
  239. }
  240.  
  241.