home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_06 / graph6.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-31  |  14.2 KB  |  579 lines

  1.  
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3.  
  4. #include <io.h>
  5. #include <conio.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <dos.h>
  9. #include <bios.h>
  10. #include <fcntl.h>
  11. #include <memory.h>
  12. #include <malloc.h>
  13. #include <math.h>
  14. #include <string.h>
  15.  
  16. #include "graph3.h"
  17. #include "graph4.h"
  18. #include "graph6.h"
  19.  
  20. // G L O B A L S  ////////////////////////////////////////////////////////////
  21.  
  22. unsigned char far *double_buffer = NULL;
  23.  
  24. unsigned int buffer_height        = SCREEN_HEIGHT;
  25.  
  26. unsigned int buffer_size = SCREEN_WIDTH*SCREEN_HEIGHT/2;
  27.  
  28. // F U N C T I O N S /////////////////////////////////////////////////////////
  29.  
  30. void Show_Double_Buffer(char far *buffer)
  31. {
  32. // this functions copies the doubele buffer into the video buffer
  33.  
  34. _asm
  35.    {
  36.    push ds               ; save DS on stack
  37.    mov cx,buffer_size    ; this is the size of buffer in WORDS
  38.    les di,video_buffer   ; es:di is destination of memory move
  39.    lds si,buffer         ; ds:si is source of memory move
  40.    cld                   ; make sure to move in the right direction
  41.    rep movsw             ; move all the words
  42.    pop ds                ; restore the data segment
  43.    } // end asm
  44.  
  45. } // end Show_Double_Buffer
  46.  
  47. //////////////////////////////////////////////////////////////////////////////
  48.  
  49. int Create_Double_Buffer(int num_lines)
  50. {
  51.  
  52. // allocate enough memory to hold the double buffer
  53.  
  54. if ((double_buffer = (unsigned char far *)_fmalloc(SCREEN_WIDTH * (num_lines + 1)))==NULL)
  55.    return(0);
  56.  
  57. // set the height of the buffer and compute it's size
  58.  
  59. buffer_height = num_lines;
  60.  
  61. buffer_size = SCREEN_WIDTH * num_lines/2;
  62.  
  63. // fill the buffer with black
  64.  
  65. _fmemset(double_buffer, 0, SCREEN_WIDTH * num_lines);
  66.  
  67. // everything was ok
  68.  
  69. return(1);
  70.  
  71. } // end Init_Double_Buffer
  72.  
  73. ///////////////////////////////////////////////////////////////////////////////
  74.  
  75. void Fill_Double_Buffer(int color)
  76. {
  77. // this function fills in the double buffer with the sent color
  78.  
  79. _fmemset(double_buffer, color, SCREEN_WIDTH * buffer_height);
  80.  
  81. } // end Fill_Double_Buffer
  82.  
  83. //////////////////////////////////////////////////////////////////////////////
  84.  
  85. void Delete_Double_Buffer(void)
  86. {
  87. // this function free's up the memory allocated by the double buffer
  88. // make sure to use FAR version
  89.  
  90. if (double_buffer)
  91.   _ffree(double_buffer);
  92.  
  93. } // end Delete_Double_Buffer
  94.  
  95. //////////////////////////////////////////////////////////////////////////////
  96.  
  97. void Plot_Pixel_Fast_DB(int x,int y,unsigned char color)
  98. {
  99.  
  100. // plots the pixel in the desired color a little quicker using binary shifting
  101. // to accomplish the multiplications
  102.  
  103. // use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6
  104.  
  105. double_buffer[((y<<8) + (y<<6)) + x] = color;
  106.  
  107. } // end Plot_Pixel_Fast_DB
  108.  
  109. //////////////////////////////////////////////////////////////////////////////
  110.  
  111. void Scale_Sprite(sprite_ptr sprite,float scale)
  112. {
  113.  
  114. // this function scales a sprite by computing the number of source pixels
  115. // needed to satisfy the number of destination pixels
  116. // note: this function works in the double buffer
  117.  
  118. char far *work_sprite;
  119.  
  120. int work_offset=0,
  121.     offset,
  122.     x,
  123.     y;
  124.  
  125. unsigned char data;
  126.  
  127. float y_scale_index,
  128.       x_scale_step,
  129.       y_scale_step,
  130.       x_scale_index;
  131.  
  132. // set first source pixel
  133.  
  134. y_scale_index = 0;
  135.  
  136. // compute floating point step
  137.  
  138. y_scale_step = sprite_height/scale;
  139. x_scale_step = sprite_width/scale;
  140.  
  141. // alias a pointer to sprite for ease of access
  142.  
  143. work_sprite = sprite->frames[sprite->curr_frame];
  144.  
  145. // compute offset of sprite in video buffer
  146.  
  147. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  148.  
  149. // row by row scale object
  150.  
  151. for (y=0; y<(int)(scale); y++)
  152.     {
  153.     // copy the next row into the screen buffer using memcpy for speed
  154.  
  155.     x_scale_index=0;
  156.  
  157.     for (x=0; x<(int)scale; x++)
  158.         {
  159.  
  160.         // test for transparent pixel i.e. 0, if not transparent then draw
  161.  
  162.         if ((data=work_sprite[work_offset+(int)x_scale_index]))
  163.              double_buffer[offset+x] = data;
  164.  
  165.         x_scale_index+=(x_scale_step);
  166.  
  167.         } // end for x
  168.  
  169.     // using the floating scale_step, index to next source pixel
  170.  
  171.     y_scale_index+=y_scale_step;
  172.  
  173.     // move to next line in video buffer and in sprite bitmap buffer
  174.  
  175.     offset      += SCREEN_WIDTH;
  176.     work_offset = sprite_width*(int)(y_scale_index);
  177.  
  178.     } // end for y
  179.  
  180. } // end Scale_Sprite
  181.  
  182. ////////////////////////////////////////////////////////////////////////////////
  183.  
  184. void Behind_Sprite_DB(sprite_ptr sprite)
  185. {
  186.  
  187. // this function scans the background behind a sprite so that when the sprite
  188. // is draw, the background isnn'y obliterated
  189.  
  190. char far *work_back;
  191. int work_offset=0,offset,y;
  192.  
  193. // alias a pointer to sprite background for ease of access
  194.  
  195. work_back = sprite->background;
  196.  
  197. // compute offset of background in video buffer
  198.  
  199. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  200.  
  201. for (y=0; y<sprite_height; y++)
  202.     {
  203.     // copy the next row out off screen buffer into sprite background buffer
  204.  
  205.     _fmemcpy((char far *)&work_back[work_offset],
  206.              (char far *)&double_buffer[offset],
  207.              sprite_width);
  208.  
  209.     // move to next line in double buffer and in sprite background buffer
  210.  
  211.     offset      += SCREEN_WIDTH;
  212.     work_offset += sprite_width;
  213.  
  214.     } // end for y
  215.  
  216. } // end Behind_Sprite_DB
  217.  
  218. //////////////////////////////////////////////////////////////////////////////
  219.  
  220. void Erase_Sprite_DB(sprite_ptr sprite)
  221. {
  222. // replace the background that was behind the sprite
  223.  
  224. // this function replaces the background that was saved from where a sprite
  225. // was going to be placed
  226.  
  227. char far *work_back;
  228. int work_offset=0,offset,y;
  229.  
  230. // alias a pointer to sprite background for ease of access
  231.  
  232. work_back = sprite->background;
  233.  
  234. // compute offset of background in double buffer
  235.  
  236. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  237.  
  238. for (y=0; y<sprite_height; y++)
  239.     {
  240.     // copy the next row out off screen buffer into sprite background buffer
  241.  
  242.     _fmemcpy((char far *)&double_buffer[offset],
  243.              (char far *)&work_back[work_offset],
  244.              sprite_width);
  245.  
  246.     // move to next line in video buffer and in sprite background buffer
  247.  
  248.     offset      += SCREEN_WIDTH;
  249.     work_offset += sprite_width;
  250.  
  251.     } // end for y
  252.  
  253.  
  254. } // end Erase_Sprite_DB
  255.  
  256. //////////////////////////////////////////////////////////////////////////////
  257.  
  258. void Draw_Sprite_DB(sprite_ptr sprite)
  259. {
  260.  
  261. // this function draws a sprite on the screen row by row very quickly
  262. // note the use of shifting to implement multplication
  263.  
  264. char far *work_sprite;
  265. int work_offset=0,offset,x,y;
  266. unsigned char data;
  267.  
  268. // alias a pointer to sprite for ease of access
  269.  
  270. work_sprite = sprite->frames[sprite->curr_frame];
  271.  
  272. // compute offset of sprite in video buffer
  273.  
  274. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  275.  
  276. for (y=0; y<sprite_height; y++)
  277.     {
  278.     // copy the next row into the double buffer using memcpy for speed
  279.  
  280.     for (x=0; x<sprite_width; x++)
  281.         {
  282.  
  283.         // test for transparent pixel i.e. 0, if not transparent then draw
  284.  
  285.         if ((data=work_sprite[work_offset+x]))
  286.              double_buffer[offset+x] = data;
  287.  
  288.         } // end for x
  289.  
  290.     // move to next line in double buffer and in sprite bitmap buffer
  291.  
  292.     offset      += SCREEN_WIDTH;
  293.     work_offset += sprite_width;
  294.  
  295.     } // end for y
  296.  
  297. } // end Draw_Sprite_DB
  298.  
  299. ///////////////////////////////////////////////////////////////////////////////
  300.  
  301. void Fade_Lights(void)
  302. {
  303. // this functions fades the lights by slowly decreasing the color values
  304. // in all color registers
  305.  
  306. int pal_reg,index;
  307. RGB_color color;
  308.  
  309. for (index=0; index<30; index++)
  310.     {
  311.  
  312.     for (pal_reg=1; pal_reg<255; pal_reg++)
  313.         {
  314.         // get the color to fade
  315.  
  316.         Get_Palette_Register(pal_reg,(RGB_color_ptr)&color);
  317.  
  318.         if (color.red   > 5) color.red-=3;
  319.         else
  320.            color.red = 0;
  321.  
  322.         if (color.green > 5) color.green-=3;
  323.         else
  324.            color.green = 0;
  325.         if (color.blue  > 5) color.blue-=3;
  326.         else
  327.            color.blue = 0;
  328.  
  329.         // set the color to a diminished intensity
  330.  
  331.         Set_Palette_Register(pal_reg,(RGB_color_ptr)&color);
  332.  
  333.         } // end for pal_reg
  334.  
  335.     // wait a bit
  336.  
  337.     Delay(2);
  338.  
  339.     } // end fade for
  340.  
  341. } // end Fade_Lights
  342.  
  343. //////////////////////////////////////////////////////////////////////////////
  344.  
  345. void Disolve(void)
  346. {
  347. // disolve screen by ploting zillions of black pixels
  348.  
  349. unsigned long index;
  350.  
  351. for (index=0; index<=300000; index++,Plot_Pixel_Fast(rand()%320, rand()%200, 0));
  352.  
  353. } // end Disolve
  354.  
  355. //////////////////////////////////////////////////////////////////////////////
  356.  
  357. void Melt(void)
  358. {
  359.  
  360. // this function "melts" the screen by moving little worms at different speeds
  361. // down the screen.  These worms change to the color thy are eating
  362.  
  363. int index,ticks=0;
  364.  
  365. worm worms[NUM_WORMS]; // the array of worms used to make the screen melt
  366.  
  367. // initialize the worms
  368.  
  369. for (index=0; index<160; index++)
  370.     {
  371.  
  372.     worms[index].color   = Get_Pixel(index,0);
  373.     worms[index].speed   = 3 + rand()%9;
  374.     worms[index].y       = 0;
  375.     worms[index].counter = 0;
  376.  
  377.     // draw the worm
  378.  
  379.     Plot_Pixel_Fast((index<<1),0,(char)worms[index].color);
  380.     Plot_Pixel_Fast((index<<1),1,(char)worms[index].color);
  381.     Plot_Pixel_Fast((index<<1),2,(char)worms[index].color);
  382.  
  383.  
  384.     Plot_Pixel_Fast((index<<1)+1,0,(char)worms[index].color);
  385.     Plot_Pixel_Fast((index<<1)+1,1,(char)worms[index].color);
  386.     Plot_Pixel_Fast((index<<1)+1,2,(char)worms[index].color);
  387.  
  388.     } // end index
  389.  
  390. // do screen melt
  391.  
  392. while(++ticks<1800)
  393.      {
  394.  
  395.      // process each worm
  396.  
  397.      for (index=0; index<320; index++)
  398.          {
  399.          // is it time to move worm
  400.  
  401.          if (++worms[index].counter == worms[index].speed)
  402.             {
  403.             // reset counter
  404.  
  405.             worms[index].counter = 0;
  406.  
  407.             worms[index].color = Get_Pixel(index,worms[index].y+4);
  408.  
  409.             // has worm hit bottom?
  410.  
  411.             if (worms[index].y < 193)
  412.                {
  413.  
  414.                Plot_Pixel_Fast((index<<1),worms[index].y,0);
  415.                Plot_Pixel_Fast((index<<1),worms[index].y+1,(char)worms[index].color);
  416.                Plot_Pixel_Fast((index<<1),worms[index].y+2,(char)worms[index].color);
  417.                Plot_Pixel_Fast((index<<1),worms[index].y+3,(char)worms[index].color);
  418.  
  419.                Plot_Pixel_Fast((index<<1)+1,worms[index].y,0);
  420.                Plot_Pixel_Fast((index<<1)+1,worms[index].y+1,(char)worms[index].color);
  421.                Plot_Pixel_Fast((index<<1)+1,worms[index].y+2,(char)worms[index].color);
  422.                Plot_Pixel_Fast((index<<1)+1,worms[index].y+3,(char)worms[index].color);
  423.  
  424.                worms[index].y++;
  425.  
  426.                } // end if worm isn't at bottom yet
  427.  
  428.             } // end if time to move worm
  429.  
  430.          } // end index
  431.  
  432.      // accelerate melt
  433.  
  434.      if (!(ticks % 500))
  435.         {
  436.  
  437.         for (index=0; index<160; index++)
  438.             worms[index].speed--;
  439.  
  440.         } // end if time to accelerate melt
  441.  
  442.      } // end while
  443.  
  444. } // end Melt
  445.  
  446. //////////////////////////////////////////////////////////////////////////////
  447.  
  448. void Sheer(void)
  449. {
  450. // this program "sheers" the screen for lack of a better word.
  451.  
  452. long index;
  453. int x,y;
  454.  
  455. // select starting point of sheers
  456.  
  457. x=rand()%320;
  458. y=rand()%200;
  459.  
  460. // do it a few times to make sure whole screen is destroyed
  461.  
  462. for (index=0; index<100000; index++)
  463.     {
  464.  
  465.     // move sheers
  466.  
  467.     x+=17; // note the use of prime numbers
  468.     y+=13;
  469.  
  470.     // test if sheers are of boundaries, if so roll them over
  471.  
  472.     if (x>319)
  473.        x = x - 319;
  474.  
  475.     if (y>199)
  476.        y = y - 199;
  477.  
  478.     // plot the pixel in black
  479.  
  480.     Plot_Pixel_Fast(x,y,0);
  481.  
  482.     } // end for index
  483.  
  484. } // end Sheer
  485.  
  486. //////////////////////////////////////////////////////////////////////////////////
  487.  
  488. void Wait_For_Vsync(void)
  489. {
  490. // this function waits for the start of a vertical retrace, if a vertical
  491. // retrace is in progress then it waits until the next one
  492.  
  493. while(_inp(VGA_INPUT_STATUS_1) & VGA_VSYNC_MASK)
  494.      {
  495.      // do nothing, vga is in retrace
  496.      } // end while
  497.  
  498. // now wait for vysnc and exit
  499.  
  500. while(!(_inp(VGA_INPUT_STATUS_1) & VGA_VSYNC_MASK))
  501.      {
  502.      // do nothing, wait for start of retrace
  503.      } // end while
  504.  
  505. // at this point a vertical retrace is occuring, so return back to caller
  506.  
  507. } // end Wait_For_Vsync
  508.  
  509. ///////////////////////////////////////////////////////////////////////////////
  510.  
  511. void Blit_Char_DB(int xc,int yc,char c,int color,int trans_flag)
  512. {
  513. // this function uses the rom 8x8 character set to blit a character into the
  514. // double buffer,notice the trick used to extract bits out of each character
  515. // byte that comprises a line
  516.  
  517. int offset,x,y;
  518. char far *work_char;
  519. unsigned char bit_mask = 0x80;
  520.  
  521. // compute starting offset in rom character lookup table
  522.  
  523. work_char = rom_char_set + c * CHAR_HEIGHT;
  524.  
  525. // compute offset of character in video buffer
  526.  
  527. offset = (yc << 8) + (yc << 6) + xc;
  528.  
  529. for (y=0; y<CHAR_HEIGHT; y++)
  530.     {
  531.     // reset bit mask
  532.  
  533.     bit_mask = 0x80;
  534.  
  535.     for (x=0; x<CHAR_WIDTH; x++)
  536.         {
  537.         // test for transparent pixel i.e. 0, if not transparent then draw
  538.  
  539.         if ((*work_char & bit_mask))
  540.              double_buffer[offset+x] = color;
  541.  
  542.         else if (!trans_flag)  // takes care of transparency
  543.             double_buffer[offset+x] = 0;
  544.  
  545.         // shift bit mask
  546.  
  547.         bit_mask = (bit_mask>>1);
  548.  
  549.         } // end for x
  550.  
  551.     // move to next line in video buffer and in rom character data area
  552.  
  553.     offset      += SCREEN_WIDTH;
  554.     work_char++;
  555.  
  556.     } // end for y
  557.  
  558. } // end Blit_Char_DB
  559.  
  560. //////////////////////////////////////////////////////////////////////////////
  561.  
  562. void Blit_String_DB(int x,int y,int color, char *string,int trans_flag)
  563. {
  564. // this function blits an entire string into the double buffer with fixed
  565. // spacing between each character.  it calls blit_char.
  566.  
  567. int index;
  568.  
  569. for (index=0; string[index]!=0; index++)
  570.      {
  571.  
  572.      Blit_Char_DB(x+(index<<3),y,string[index],color,trans_flag);
  573.  
  574.      } /* end while */
  575.  
  576. } /* end Blit_String_DB */
  577.  
  578. ///////////////////////////////////////////////////////////////////////////////
  579.