home *** CD-ROM | disk | FTP | other *** search
/ Black Art of 3D Game Programming / Black_Art_of_3D_Game_Programming.iso / source / msc / chap_8 / volcano.c < prev    next >
Text File  |  1994-11-23  |  8KB  |  296 lines

  1.  
  2. // VOLCANO.C - A demo of multiple data single logic programming
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17.  
  18. #include "black3.h"
  19. #include "black4.h"
  20. #include "black8.h"
  21.  
  22. // D E F I N E S ////////////////////////////////////////////////////////////
  23.  
  24. #define MAX_CINDERS        100  // maximum number of cinders in the simulation
  25.  
  26. #define VOLCANO_MOUTH_X    145  // position where cinders will be emitted
  27. #define VOLCANO_MOUTH_Y    102
  28.  
  29. #define CINDER_START_COLOR 48     // starting cinder color
  30. #define CINDER_END_COLOR   48+15  // ending cinder color
  31.  
  32. // S T R U C T U R E S //////////////////////////////////////////////////////
  33.  
  34. typedef struct cinder_typ
  35.         {
  36.         int x,y;         // position of cinder
  37.         int xv,yv;       // velocity of cinder
  38.         int color;       // color of cinder
  39.         int lifetime;    // total number of frames cinder will live for
  40.         int counter_1;   // tracks when cinder color will change
  41.         int threshold_1; //
  42.         int counter_2;   // tracks when gravity will be applied
  43.         int threshold_2;
  44.         int col;         // the current color of the cinder
  45.         int under;       // this holds the pixel under the cinder
  46.  
  47.         } cinder, *cinder_ptr;
  48.  
  49. // G L O B A L S  ////////////////////////////////////////////////////////////
  50.  
  51. pcx_picture image_pcx;  // general PCX image used to load background and imagery
  52.  
  53. cinder cinders[MAX_CINDERS];  // this holds all the cinders
  54. int active_cinders;           // nunmbr of active cinders in the world
  55.  
  56. // F U N C T I O N S /////////////////////////////////////////////////////////
  57.  
  58. void Init_Cinders(int starting_cinder, int ending_cinder)
  59. {
  60. // this function initializes cinders, it can initialize a sequence of cinders,
  61. // or a single cinder
  62.  
  63. int index; // looping variable
  64.  
  65. // intialize each cinder or restart a single cinder
  66.  
  67. for (index=starting_cinder; index<=ending_cinder; index++)
  68.     {
  69.     // fill in position, velocity and color of cinder
  70.  
  71.     cinders[index].x = VOLCANO_MOUTH_X - 5 + rand() % 11;
  72.     cinders[index].y = VOLCANO_MOUTH_Y - rand() % 3;
  73.  
  74.     cinders[index].xv = - 2 + rand() % 5;
  75.     cinders[index].yv = - 5 - rand() % 5;
  76.  
  77.     cinders[index].col = CINDER_START_COLOR;
  78.  
  79.     // scan under cinder
  80.  
  81.     cinders[index].under = Read_Pixel_DB(cinders[index].x,cinders[index].y);
  82.  
  83.     // set timing fields
  84.  
  85.     cinders[index].lifetime = 20 + rand()%100;
  86.  
  87.     cinders[index].counter_1 = 0;
  88.     cinders[index].counter_2 = 0;
  89.  
  90.     // set how long it will take for cinder to cool
  91.  
  92.     cinders[index].threshold_1 = 2 + rand()%6;
  93.  
  94.     // set how long it will take for gravity to take effect
  95.  
  96.     cinders[index].threshold_2 = 1+rand()%3;
  97.  
  98.     } // end for index
  99.  
  100. } // end Init_Cinders
  101.  
  102. /////////////////////////////////////////////////////////////////////////////
  103.  
  104. void Erase_Cinders(void)
  105. {
  106. // this function replaces the pixel that was under a cinder
  107.  
  108. int index; // looping variable
  109.  
  110. for (index=0; index<active_cinders; index++)
  111.     if (cinders[index].y >=0)
  112.         Write_Pixel_DB(cinders[index].x,cinders[index].y,cinders[index].under);
  113.  
  114. } // end Erase_Cinders
  115.  
  116. /////////////////////////////////////////////////////////////////////////////
  117.  
  118. void Scan_Cinders(void)
  119. {
  120. // this function scan under the cinders
  121.  
  122. int index; // looping variable
  123.  
  124. for (index=0; index<active_cinders; index++)
  125.     if (cinders[index].y >=0)
  126.         cinders[index].under = Read_Pixel_DB(cinders[index].x,cinders[index].y);
  127.  
  128. } // end Scan_Cinders
  129.  
  130. /////////////////////////////////////////////////////////////////////////////
  131.  
  132. void Draw_Cinders(void)
  133. {
  134. // this function draws the cinders
  135.  
  136. int index; // looping variable
  137.  
  138. for (index=0; index<active_cinders; index++)
  139.     if (cinders[index].y >=0)
  140.         Write_Pixel_DB(cinders[index].x,cinders[index].y,cinders[index].col);
  141.  
  142. } // end Draw_Cinders
  143.  
  144. /////////////////////////////////////////////////////////////////////////////
  145.  
  146. void Move_Cinders(void)
  147. {
  148. // this function moves and updates all the timing fields of the cinder
  149. // it also applies gravity to the cinders
  150.  
  151. int index, // looping variable
  152.     pixel; // used to read the pixels under the cinder
  153.  
  154.  
  155. // process each cinder
  156.  
  157. for (index=0; index<active_cinders; index++)
  158.     {
  159.     // move the cinder
  160.  
  161.     cinders[index].x+=cinders[index].xv;
  162.     cinders[index].y+=cinders[index].yv;
  163.  
  164.     // apply gravity
  165.  
  166.     if (++cinders[index].counter_2 >= cinders[index].threshold_2)
  167.        {
  168.        // apply a downward velocity of 1
  169.        cinders[index].yv++;
  170.  
  171.        // reset gravity counter
  172.        cinders[index].counter_2 = 0;
  173.  
  174.        } // end if time to update gravity
  175.  
  176.     // test if it's time to update cinder color
  177.  
  178.     if (++cinders[index].counter_1 >=cinders[index].threshold_1)
  179.        {
  180.        // reset counter
  181.        cinders[index].counter_1 = 0;
  182.  
  183.        // test if cinder is already out
  184.  
  185.        if (cinders[index].col < CINDER_END_COLOR)
  186.           cinders[index].col++;
  187.  
  188.        } // end if time for color change
  189.  
  190.     // test if cinder is dead, off screen, lifetime over, or hit moutain
  191.  
  192.     pixel = Read_Pixel_DB(cinders[index].x,cinders[index].y);
  193.  
  194.     // test if the pixel is part of the mountain
  195.  
  196.     if (pixel!=0 && (pixel < CINDER_START_COLOR || pixel > CINDER_END_COLOR))
  197.        {
  198.        // restart this cinder
  199.  
  200.        Init_Cinders(index,index);
  201.  
  202.        } // end if cinder hit mountain
  203.     else
  204.     if (--cinders[index].lifetime <= 0)
  205.        {
  206.        // restart this cinder
  207.  
  208.        Init_Cinders(index,index);
  209.  
  210.        } // end if cinders lifetime expired
  211.     else
  212.     if (cinders[index].x > 320 || cinders[index].x < 0)
  213.        {
  214.        // restart this cinder
  215.  
  216.        Init_Cinders(index,index);
  217.  
  218.        } // end if cinder is off screen
  219.  
  220.     } // end for index
  221.  
  222. } // end Move_Cinders
  223.  
  224. // M A I N //////////////////////////////////////////////////////////////////
  225.  
  226. void main(int argc, char **argv)
  227. {
  228.  
  229. // set the graphics mode to mode 13h
  230.  
  231. Set_Graphics_Mode(GRAPHICS_MODE13);
  232.  
  233. // create the double buffer
  234.  
  235. Create_Double_Buffer(200);
  236.  
  237. // now load the background image
  238.  
  239. PCX_Init((pcx_picture_ptr)&image_pcx);
  240. PCX_Load("volcano.pcx",(pcx_picture_ptr)&image_pcx,1);
  241.  
  242. // copy PCX image to double buffer
  243.  
  244. PCX_Copy_To_Buffer((pcx_picture_ptr)&image_pcx,double_buffer);
  245. PCX_Delete((pcx_picture_ptr)&image_pcx);
  246.  
  247. // draw instructions
  248.  
  249. Print_String_DB(80,2,9,"Hit any key to exit",1);
  250.  
  251. // intialize all the cinders
  252.  
  253. Init_Cinders(0,19);
  254.  
  255. active_cinders = 20;
  256.  
  257. // main event loop, process until keyboard hit
  258.  
  259. while(!kbhit())
  260.      {
  261.      // erase all the cinders coming out of the volcano
  262.  
  263.      Erase_Cinders();
  264.  
  265.      // move all the cinders
  266.  
  267.      Move_Cinders();
  268.  
  269.      // scan under and draw the cinders
  270.  
  271.      Scan_Cinders();
  272.      Draw_Cinders();
  273.  
  274.      // display double buffer
  275.  
  276.      Display_Double_Buffer(double_buffer,0);
  277.  
  278.      // lock onto 18 frames per second max
  279.  
  280.      Time_Delay(1);
  281.  
  282.      } // end while
  283.  
  284. // exit in a very cool way
  285.  
  286. Screen_Transition(SCREEN_DARKNESS);
  287.  
  288. // free up all resources
  289.  
  290. Delete_Double_Buffer();
  291.  
  292. Set_Graphics_Mode(TEXT_MODE);
  293.  
  294. } // end main
  295.  
  296.