home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_06 / scalar.c < prev    next >
Text File  |  1994-05-23  |  7KB  |  312 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" // include our graphics library
  17. #include "graph4.h" // include our graphics library
  18.  
  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. sprite object;
  29.  
  30. pcx_picture imagery_pcx;
  31.  
  32. // F U N C T I O N S //////////////////////////////////////////////////////////
  33.  
  34. void Show_Double_Buffer(unsigned char far *buffer)
  35. {
  36. // this functions copies the double buffer into the video buffer
  37.  
  38. _asm
  39.    {
  40.    push ds               ; save DS on stack
  41.    mov cx,buffer_size    ; this is the size of buffer in WORDS
  42.    les di,video_buffer   ; es:di is destination of memory move
  43.    lds si,buffer         ; ds:si is source of memory move
  44.    cld                   ; make sure to move in the right direction
  45.    rep movsw             ; move all the words
  46.    pop ds                ; restore the data segment
  47.    } // end asm
  48.  
  49. } // end Show_Double_Buffer
  50.  
  51. //////////////////////////////////////////////////////////////////////////////
  52.  
  53. int Create_Double_Buffer(int num_lines)
  54. {
  55.  
  56. // allocate enough memory to hold the double buffer
  57.  
  58. if ((double_buffer = (unsigned char far *)_fmalloc(SCREEN_WIDTH * (num_lines + 1)))==NULL)
  59.    return(0);
  60.  
  61. // set the height of the buffer and compute it's size
  62.  
  63. buffer_height = num_lines;
  64.  
  65. buffer_size = SCREEN_WIDTH * num_lines/2;
  66.  
  67. // fill the buffer with black
  68.  
  69. _fmemset(double_buffer, 0, SCREEN_WIDTH * num_lines);
  70.  
  71. // everything was ok
  72.  
  73. return(1);
  74.  
  75. } // end Init_Double_Buffer
  76.  
  77. ///////////////////////////////////////////////////////////////////////////////
  78.  
  79. void Fill_Double_Buffer(int color)
  80. {
  81. // this function fills in the double buffer with the sent color
  82.  
  83. _fmemset(double_buffer, color, SCREEN_WIDTH * buffer_height);
  84.  
  85. } // end Fill_Double_Buffer
  86.  
  87. //////////////////////////////////////////////////////////////////////////////
  88.  
  89. void Delete_Double_Buffer(void)
  90. {
  91. // this function free's up the memory allocated by the double buffer
  92. // make sure to use FAR version
  93.  
  94. if (double_buffer)
  95.   _ffree(double_buffer);
  96.  
  97. } // end Delete_Double_Buffer
  98.  
  99. ///////////////////////////////////////////////////////////////////////////////
  100.  
  101. void Scale_Sprite(sprite_ptr sprite,float scale)
  102. {
  103.  
  104. // this function scales a sprite by computing the number of source pixels
  105. // needed to satisfy the number of destination pixels
  106. // note: this function works in the double buffer
  107.  
  108. char far *work_sprite;
  109.  
  110. int work_offset=0,
  111.     offset,
  112.     x,
  113.     y;
  114.  
  115. unsigned char data;
  116.  
  117. float y_scale_index,
  118.       x_scale_step,
  119.       y_scale_step,
  120.       x_scale_index;
  121.  
  122. // set first source pixel
  123.  
  124. y_scale_index = 0;
  125.  
  126. // compute floating point step
  127.  
  128. y_scale_step = sprite_height/scale;
  129. x_scale_step = sprite_width/scale;
  130.  
  131. // alias a pointer to sprite for ease of access
  132.  
  133. work_sprite = sprite->frames[sprite->curr_frame];
  134.  
  135. // compute offset of sprite in video buffer
  136.  
  137. offset = (sprite->y << 8) + (sprite->y << 6) + sprite->x;
  138.  
  139. // row by row scale object
  140.  
  141. for (y=0; y<(int)(scale); y++)
  142.     {
  143.     // copy the next row into the screen buffer using memcpy for speed
  144.  
  145.     x_scale_index=0;
  146.  
  147.     for (x=0; x<(int)scale; x++)
  148.         {
  149.  
  150.         // test for transparent pixel i.e. 0, if not transparent then draw
  151.  
  152.         if ((data=work_sprite[work_offset+(int)x_scale_index]))
  153.              double_buffer[offset+x] = data;
  154.  
  155.         x_scale_index+=(x_scale_step);
  156.  
  157.         } // end for x
  158.  
  159.     // using the floating scale_step, index to next source pixel
  160.  
  161.     y_scale_index+=y_scale_step;
  162.  
  163.     // move to next line in video buffer and in sprite bitmap buffer
  164.  
  165.     offset      += SCREEN_WIDTH;
  166.     work_offset = sprite_width*(int)(y_scale_index);
  167.  
  168.     } // end for y
  169.  
  170. } // end Scale_Sprite
  171.  
  172. // M A I N ///////////////////////////////////////////////////////////////////
  173.  
  174. void main(void)
  175. {
  176. int done=0;        // exit flag
  177. char buffer[128];  // used to build up info string
  178.  
  179. float scale=32; // initial scale of object
  180.  
  181. // set video mode to 320x200 256 color mode
  182.  
  183. Set_Video_Mode(VGA256);
  184.  
  185. // set sprite system size so that functions use correct sprite size
  186.  
  187. sprite_width = sprite_height = 32;
  188.  
  189. // initialize the pcx file that holds all the animation cells for net-tank
  190.  
  191. PCX_Init((pcx_picture_ptr)&imagery_pcx);
  192.  
  193. // load the pcx file that holds the cells
  194.  
  195. PCX_Load("robopunk.pcx", (pcx_picture_ptr)&imagery_pcx,1);
  196.  
  197. Sprite_Init((sprite_ptr)&object,0,0,0,0,0,0);
  198.  
  199. // grap the bitmap
  200.  
  201. PCX_Grab_Bitmap((pcx_picture_ptr)&imagery_pcx,(sprite_ptr)&object,0,3,0);
  202.  
  203. // create a double buffer
  204.  
  205. if (!Create_Double_Buffer(SCREEN_HEIGHT))
  206.    {
  207.    printf("\nNot enough memory to create double buffer.");
  208.  
  209.    } // end if
  210.  
  211. // initialize the sprite
  212.  
  213. object.curr_frame = 0;
  214. object.x          = 160-(sprite_width>>1);
  215. object.y          = 100-(sprite_height>>1);
  216.  
  217. // clear the double buffer
  218.  
  219. Fill_Double_Buffer(0);
  220.  
  221. // show the user the scaled texture
  222.  
  223. Scale_Sprite((sprite_ptr)&object,scale);
  224.  
  225. Show_Double_Buffer(double_buffer);
  226.  
  227. Blit_String(0,190,10,"Press 'Q' to Quit,'<' '>' to Scale.",1);
  228.  
  229. // main loop
  230.  
  231. while(!done)
  232.      {
  233.  
  234.      // has user hit a key?
  235.  
  236.      if (kbhit())
  237.         {
  238.         switch(getch())
  239.               {
  240.               case '.': // scale object larger
  241.                    {
  242.                    if (scale<180)
  243.                       {
  244.                       scale+=4;
  245.                       object.x-=2;
  246.                       object.y-=2;
  247.                       } // end if ok to scale larger
  248.  
  249.                    } break;
  250.  
  251.               case ',': // scale object smaller
  252.                    {
  253.                    if (scale>4)
  254.                       {
  255.                       scale-=4;
  256.                       object.x+=2;
  257.                       object.y+=2;
  258.                       } // end if ok to scale smaller
  259.  
  260.                    } break;
  261.  
  262.               case 'q': // let's go!
  263.                       {
  264.                       done=1;
  265.                       } break;
  266.  
  267.               default:break;
  268.  
  269.               } // end switch
  270.  
  271.  
  272.         // create a clean slate
  273.  
  274.         Fill_Double_Buffer(0);
  275.  
  276.         // scale the sprite and render into the double buffer
  277.  
  278.         Scale_Sprite((sprite_ptr)&object,scale);
  279.  
  280.         // show the double buffer
  281.  
  282.         Show_Double_Buffer(double_buffer);
  283.  
  284.         Blit_String(0,190,10,"Press 'Q' to Quit,'<' '>' to Scale.",1);
  285.  
  286.         sprintf(buffer,"Current scale = %f  ",scale/32);
  287.  
  288.         Blit_String(0,8,10,buffer,1);
  289.  
  290.  
  291.         }// end if
  292.  
  293.      } // end while
  294.  
  295. // delete the pcx file
  296.  
  297. PCX_Delete((pcx_picture_ptr)&imagery_pcx);
  298.  
  299. // go back to text mode
  300.  
  301. Set_Video_Mode(TEXT_MODE);
  302.  
  303. // delete the doubele buffer
  304.  
  305. Delete_Double_Buffer();
  306.  
  307.  
  308. } // end main
  309.  
  310.  
  311.  
  312.