home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_04 / graph4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-25  |  11.1 KB  |  451 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" // load in module 3's header
  17. #include "graph4.h" // load in this modules header
  18.  
  19. // G L O B A L S  ////////////////////////////////////////////////////////////
  20.  
  21. unsigned int sprite_width  = SPRITE_WIDTH; // default height and width of sprite
  22. unsigned int sprite_height = SPRITE_HEIGHT;
  23.  
  24. // F U N C T I O N S /////////////////////////////////////////////////////////
  25.  
  26. unsigned char Get_Pixel(int x,int y)
  27. {
  28.  
  29. // gets the color value of pixel at (x,y) from the screen and returns it
  30.  
  31. return video_buffer[((y<<8) + (y<<6)) + x];
  32.  
  33. } // end Get_Pixel
  34.  
  35. //////////////////////////////////////////////////////////////////////////////
  36.  
  37. void PCX_Init(pcx_picture_ptr image)
  38. {
  39. // this function allocates the buffer region needed to load a pcx file
  40.  
  41. if (!(image->buffer = (char far *)_fmalloc(SCREEN_WIDTH * SCREEN_HEIGHT + 1)))
  42.  
  43.    printf("\ncouldn't allocate screen buffer");
  44.  
  45. } // end PCX_Init
  46.  
  47. //////////////////////////////////////////////////////////////////////////////
  48.  
  49. void PCX_Load(char *filename, pcx_picture_ptr image,int enable_palette)
  50. {
  51. // this function loads a pcx file into a picture structure, the actual image
  52. // data for the pcx file is decompressed and expanded into a secondary buffer
  53. // within the picture structure, the separate images can be grabbed from this
  54. // buffer later.  also the header and palette are loaded
  55.  
  56. FILE *fp;
  57. int num_bytes,index;
  58. long count;
  59. unsigned char data;
  60. char far *temp_buffer;
  61.  
  62. // open the file
  63.  
  64. fp = fopen(filename,"rb");
  65.  
  66. // load the header
  67.  
  68. temp_buffer = (char far *)image;
  69.  
  70. for (index=0; index<128; index++)
  71.     {
  72.     temp_buffer[index] = (char)getc(fp);
  73.     } // end for index
  74.  
  75. // load the data and decompress into buffer
  76.  
  77. count=0;
  78.  
  79. while(count<=SCREEN_WIDTH * SCREEN_HEIGHT)
  80.      {
  81.      // get the first piece of data
  82.  
  83.      data = (unsigned char)getc(fp);
  84.  
  85.      // is this a rle?
  86.  
  87.      if (data>=192 && data<=255)
  88.         {
  89.         // how many bytes in run?
  90.  
  91.         num_bytes = data-192;
  92.  
  93.         // get the actual data for the run
  94.  
  95.         data  = (unsigned char)getc(fp);
  96.  
  97.         // replicate data in buffer num_bytes times
  98.  
  99.         while(num_bytes-->0)
  100.              {
  101.              image->buffer[count++] = data;
  102.  
  103.              } // end while
  104.  
  105.         } // end if rle
  106.      else
  107.         {
  108.         // actual data, just copy it into buffer at next location
  109.  
  110.         image->buffer[count++] = data;
  111.  
  112.         } // end else not rle
  113.  
  114.      } // end while
  115.  
  116. // move to end of file then back up 768 bytes i.e. to begining of palette
  117.  
  118. fseek(fp,-768L,SEEK_END);
  119.  
  120. // load the pallete into the palette
  121.  
  122. for (index=0; index<256; index++)
  123.     {
  124.     // get the red component
  125.  
  126.     image->palette[index].red   = (unsigned char)(getc(fp) >> 2);
  127.  
  128.     // get the green component
  129.  
  130.     image->palette[index].green = (unsigned char)(getc(fp) >> 2);
  131.  
  132.     // get the blue component
  133.  
  134.     image->palette[index].blue  = (unsigned char)(getc(fp) >> 2);
  135.  
  136.     } // end for index
  137.  
  138. fclose(fp);
  139.  
  140. // change the palette to newly loaded palette if commanded to do so
  141.  
  142. if (enable_palette)
  143.    {
  144.  
  145.    // for each palette register set to the new color values
  146.  
  147.    for (index=0; index<256; index++)
  148.        {
  149.  
  150.        Set_Palette_Register(index,(RGB_color_ptr)&image->palette[index]);
  151.  
  152.        } // end for index
  153.  
  154.    } // end if change palette
  155.  
  156. } // end PCX_Load
  157.  
  158. //////////////////////////////////////////////////////////////////////////////
  159.  
  160. void PCX_Delete(pcx_picture_ptr image)
  161. {
  162. // this function de-allocates the buffer region used for the pcx file load
  163.  
  164. _ffree(image->buffer);
  165.  
  166. } // end PCX_Delete
  167.  
  168. //////////////////////////////////////////////////////////////////////////////
  169.  
  170. void PCX_Show_Buffer(pcx_picture_ptr image)
  171. {
  172. // just copy he pcx buffer into the video buffer
  173.  
  174. char far *data;
  175.  
  176. data = image->buffer;
  177.  
  178. _asm
  179.    {
  180.    push ds               ; save the data segment
  181.    les di, video_buffer  ; point es:di to video buffer
  182.    lds si, data          ; point ds:si to data area
  183.    mov cx,320*200/2      ; move 32000 words
  184.    cld                   ; set direction to foward
  185.    rep movsw             ; do the string operation
  186.    pop ds                ; restore the data segment
  187.    }
  188.  
  189. } // end PCX_Show_Picture
  190.  
  191. //////////////////////////////////////////////////////////////////////////////
  192.  
  193. void Sprite_Init(sprite_ptr sprite,int x,int y,int ac,int as,int mc,int ms)
  194. {
  195. // this function initializes a sprite with the sent data
  196.  
  197. int index;
  198.  
  199. sprite->x            = x;
  200. sprite->y            = y;
  201. sprite->x_old        = x;
  202. sprite->y_old        = y;
  203. sprite->width        = sprite_width;
  204. sprite->height       = sprite_height;
  205. sprite->anim_clock   = ac;
  206. sprite->anim_speed   = as;
  207. sprite->motion_clock = mc;
  208. sprite->motion_speed = ms;
  209. sprite->curr_frame   = 0;
  210. sprite->state        = SPRITE_DEAD;
  211. sprite->num_frames   = 0;
  212. sprite->background   = (char far *)_fmalloc(sprite_width * sprite_height+1);
  213.  
  214. // set all bitmap pointers to null
  215.  
  216. for (index=0; index<MAX_SPRITE_FRAMES; index++)
  217.     sprite->frames[index] = NULL;
  218.  
  219. } // end Sprite_Init
  220.  
  221. //////////////////////////////////////////////////////////////////////////////
  222.  
  223. void Sprite_Delete(sprite_ptr sprite)
  224. {
  225. // this function deletes all the memory associated with a sprire
  226.  
  227. int index;
  228.  
  229. _ffree(sprite->background);
  230.  
  231. // now de-allocate all the animation frames
  232.  
  233. for (index=0; index<MAX_SPRITE_FRAMES; index++)
  234.     _ffree(sprite->frames[index]);
  235.  
  236. } // end Sprite_Delete
  237.  
  238.  
  239. //////////////////////////////////////////////////////////////////////////////
  240.  
  241. void PCX_Grab_Bitmap(pcx_picture_ptr image,
  242.                      sprite_ptr sprite,
  243.                      int sprite_frame,
  244.                      int grab_x, int grab_y)
  245.  
  246. {
  247. // this function will grap a bitmap from the pcx frame buffer. it uses the
  248. // convention that the 320x200 pixel matrix is sub divided into a smaller
  249. // matrix of nxn adjacent squares
  250.  
  251. int x_off,y_off, x,y;
  252. char far *sprite_data;
  253.  
  254. // first allocate the memory for the sprite in the sprite structure
  255.  
  256. sprite->frames[sprite_frame] = (char far *)_fmalloc(sprite_width * sprite_height + 1);
  257.  
  258. // create an alias to the sprite frame for ease of access
  259.  
  260. sprite_data = sprite->frames[sprite_frame];
  261.  
  262. // now load the sprite data into the sprite frame array from the pcx picture
  263.  
  264. x_off = (sprite_width+1)  * grab_x + 1;
  265. y_off = (sprite_height+1) * grab_y + 1;
  266.  
  267. // compute starting y address
  268.  
  269. y_off = y_off * 320;
  270.  
  271. for (y=0; y<sprite_height; y++)
  272.     {
  273.  
  274.     for (x=0; x<sprite_width; x++)
  275.         {
  276.  
  277.         // get the next byte of current row and place into next position in
  278.         // sprite frame data buffer
  279.  
  280.         sprite_data[y*sprite_width + x] = image->buffer[y_off + x_off + x];
  281.  
  282.         } // end for x
  283.  
  284.         // move to next line of picture buffer
  285.  
  286.         y_off+=320;
  287.  
  288.     } // end for y
  289.  
  290. // increment number of frames
  291.  
  292. sprite->num_frames++;
  293.  
  294. // done!, let's bail!
  295.  
  296. } // end PCX_Grab_Bitmap
  297.  
  298. //////////////////////////////////////////////////////////////////////////////
  299.  
  300. void Behind_Sprite(sprite_ptr sprite)
  301. {
  302.  
  303. // this function scans the background behind a sprite so that when the sprite
  304. // is draw, the background isnn'y obliterated
  305.  
  306. char far *work_back;
  307. int work_offset=0,offset,y;
  308.  
  309. // alias a pointer to sprite background for ease of access
  310.  
  311. work_back = sprite->background;
  312.  
  313. // compute offset of background in video buffer
  314.  
  315. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  316.  
  317. for (y=0; y<sprite_height; y++)
  318.     {
  319.     // copy the next row out off screen buffer into sprite background buffer
  320.  
  321.     _fmemcpy((char far *)&work_back[work_offset],
  322.              (char far *)&video_buffer[offset],
  323.              sprite_width);
  324.  
  325.     // move to next line in video buffer and in sprite background buffer
  326.  
  327.     offset      += SCREEN_WIDTH;
  328.     work_offset += sprite_width;
  329.  
  330.     } // end for y
  331.  
  332. } // end Behind_Sprite
  333.  
  334. //////////////////////////////////////////////////////////////////////////////
  335.  
  336. void Erase_Sprite(sprite_ptr sprite)
  337. {
  338. // replace the background that was behind the sprite
  339.  
  340. // this function replaces the background that was saved from where a sprite
  341. // was going to be placed
  342.  
  343. char far *work_back;
  344. int work_offset=0,offset,y;
  345.  
  346. // alias a pointer to sprite background for ease of access
  347.  
  348. work_back = sprite->background;
  349.  
  350. // compute offset of background in video buffer
  351.  
  352. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  353.  
  354. for (y=0; y<sprite_height; y++)
  355.     {
  356.     // copy the next row out off screen buffer into sprite background buffer
  357.  
  358.     _fmemcpy((char far *)&video_buffer[offset],
  359.              (char far *)&work_back[work_offset],
  360.              sprite_width);
  361.  
  362.     // move to next line in video buffer and in sprite background buffer
  363.  
  364.     offset      += SCREEN_WIDTH;
  365.     work_offset += sprite_width;
  366.  
  367.     } // end for y
  368.  
  369.  
  370. } // end Erase_Sprite
  371.  
  372. //////////////////////////////////////////////////////////////////////////////
  373.  
  374. void Draw_Sprite(sprite_ptr sprite)
  375. {
  376.  
  377. // this function draws a sprite on the screen row by row very quickly
  378. // note the use of shifting to implement multplication
  379.  
  380. char far *work_sprite;
  381. int work_offset=0,offset,x,y;
  382. unsigned char data;
  383.  
  384. // alias a pointer to sprite for ease of access
  385.  
  386. work_sprite = sprite->frames[sprite->curr_frame];
  387.  
  388. // compute offset of sprite in video buffer
  389.  
  390. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  391.  
  392. for (y=0; y<sprite_height; y++)
  393.     {
  394.     // copy the next row into the screen buffer using memcpy for speed
  395.  
  396.     for (x=0; x<sprite_width; x++)
  397.         {
  398.  
  399.         // test for transparent pixel i.e. 0, if not transparent then draw
  400.  
  401.         data=work_sprite[work_offset+x];
  402.  
  403.         if (data)
  404.              video_buffer[offset+x] = data;
  405.  
  406.         } // end for x
  407.  
  408.     // move to next line in video buffer and in sprite bitmap buffer
  409.  
  410.     offset      += SCREEN_WIDTH;
  411.     work_offset += sprite_width;
  412.  
  413.     } // end for y
  414.  
  415. } // end Draw_Sprite
  416.  
  417. ///////////////////////////////////////////////////////////////////////////////
  418.  
  419. int Sprite_Collide(sprite_ptr sprite_1, sprite_ptr sprite_2)
  420. {
  421. // this function tests the bounding boxes of each sprite to see if a
  422. // collision has occured, if so a 1 is returned else a 0 is returned
  423.  
  424. int dx,dy;
  425.  
  426. // compute amount of overlap, if any
  427.  
  428. dx = abs(sprite_1->x - sprite_2->x);
  429. dy = abs(sprite_1->y - sprite_2->y);
  430.  
  431. // test x and y extents, note how the width and height are decreased by a
  432. // percentage of the actual width and height. this is to make the bounding
  433. // box a little more realistic since very seldomly will an object be
  434. // rectangula, this helps to insure that there is a solid collision
  435.  
  436. if (dx<(sprite_width-(sprite_width>>3)) && dy<(sprite_height-(sprite_height>>3)))
  437.    {
  438.  
  439.    return(1);
  440.  
  441.    } // end if collision occured
  442. else
  443.    {
  444.  
  445.    return(0);
  446.  
  447.    } // end else
  448.  
  449. } // end Sprite_Collide
  450.  
  451.