home *** CD-ROM | disk | FTP | other *** search
/ Black Art of 3D Game Programming / Black_Art_of_3D_Game_Programming.iso / source / borland / chap_7 / critters.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-17  |  5.4 KB  |  221 lines

  1.  
  2. // CRITTERS.C - A demo of converge or flocking
  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.  
  21. // D E F I N E S /////////////////////////////////////////////////////////////
  22.  
  23. #define NUM_CRITTERS  200
  24.  
  25. // S T R U C T U R E S ///////////////////////////////////////////////////////
  26.  
  27. typedef struct critter_typ
  28.         {
  29.  
  30.         float x,y,    // position of critter
  31.               xv,yv;  // velocity of critter
  32.  
  33.         int back;     // the background color under the critter
  34.  
  35.         } critter, *critter_ptr;
  36.  
  37. // G L O B A L S  ////////////////////////////////////////////////////////////
  38.  
  39. pcx_picture image_pcx;  // general PCX image used to load background and imagery
  40.  
  41. critter critters[NUM_CRITTERS];  // the array that hold all the critters
  42.  
  43. // M A I N //////////////////////////////////////////////////////////////////
  44.  
  45. void main(int argc, char **argv)
  46. {
  47.  
  48. int index;   // loop variable
  49.  
  50.  
  51. float speed,        // used to scale velocity vector of trajectory
  52.       dx,dy,        // used to compute trajectory vectors
  53.       length,       // length of trajectory vector, used to normalize
  54.       centroid_x,   // center of mass of all critters
  55.       centroid_y;
  56.  
  57. // set the graphics mode to mode 13h
  58.  
  59. Set_Graphics_Mode(GRAPHICS_MODE13);
  60.  
  61. // create the double buffer
  62.  
  63. Create_Double_Buffer(200);
  64.  
  65. // now load the background image
  66.  
  67. PCX_Init((pcx_picture_ptr)&image_pcx);
  68. PCX_Load("critback.pcx",(pcx_picture_ptr)&image_pcx,1);
  69.  
  70. // copy PCX image to double buffer
  71.  
  72. PCX_Copy_To_Buffer((pcx_picture_ptr)&image_pcx,double_buffer);
  73. PCX_Delete((pcx_picture_ptr)&image_pcx);
  74.  
  75. // put up exit instructions
  76.  
  77. Print_String_DB(80,2,9,"Hit any key to exit",1);
  78.  
  79. // create the arrays of little critters
  80.  
  81. for (index=0; index<NUM_CRITTERS; index++)
  82.     {
  83.  
  84.     // select a random position for critter
  85.  
  86.     critters[index].x = rand()%320;
  87.     critters[index].y = rand()%200;
  88.  
  89.     } // end for index
  90.  
  91. // now compute the meeting place for the critters. This could be any point
  92. // you wish, but in this case we'll use their centroid, but in many cases you
  93. // may want them to converge upon a player or specific spot
  94.  
  95. centroid_x = 0;
  96. centroid_y = 0;
  97.  
  98. for (index=0; index<NUM_CRITTERS; index++)
  99.     {
  100.  
  101.     // average in next critter position
  102.  
  103.     centroid_x+=critters[index].x;
  104.     centroid_y+=critters[index].y;
  105.  
  106.     } // end for index
  107.  
  108. // compute final average
  109.  
  110. centroid_x/=(float)NUM_CRITTERS;
  111. centroid_y/=(float)NUM_CRITTERS;
  112.  
  113. // mark centroid
  114.  
  115. Print_String_DB(centroid_x,centroid_y,15,"C",1);
  116.  
  117. // now vector each critter toward centroid on a straight line trajectory
  118.  
  119. for (index=0; index<NUM_CRITTERS; index++)
  120.     {
  121.     // compute deltas
  122.  
  123.     dx = centroid_x-critters[index].x;
  124.     dy = centroid_y-critters[index].y;
  125.  
  126.     // compute a unit vector pointing toward centroid for this critter
  127.  
  128.     length = sqrt(dx*dx+dy*dy);
  129.  
  130.     dx = dx/length;
  131.     dy = dy/length;
  132.  
  133.     // now scale the vector by some factor to synthesize velocity
  134.  
  135.     speed = 2 + rand()%3;
  136.  
  137.     // compute trajectory vector
  138.  
  139.     critters[index].xv = dx*speed;
  140.     critters[index].yv = dy*speed;
  141.  
  142.     } // end for index
  143.  
  144. // scan under all critters
  145.  
  146. for (index=0; index<NUM_CRITTERS; index++)
  147.     critters[index].back = Read_Pixel_DB((int)critters[index].x,
  148.                                          (int)critters[index].y);
  149.  
  150. // main event loop, process until keyboard hit
  151.  
  152. while(!kbhit())
  153.      {
  154.  
  155.      // do animation cycle, erase, move draw...
  156.  
  157.      // erase all critters by replacing what was under them
  158.  
  159.      for (index=0; index<NUM_CRITTERS; index++)
  160.          Write_Pixel_DB((int)critters[index].x,
  161.                         (int)critters[index].y,
  162.                         critters[index].back);
  163.  
  164. // BEGIN CONVERGENCE CODE ////////////////////////////////////////////////////
  165.  
  166.      // move critters toward centroid if they are far enough away
  167.  
  168.      for (index=0; index<NUM_CRITTERS; index++)
  169.          {
  170.  
  171.          // test if critter is far enough away from centroid use
  172.          // manhattan distance
  173.  
  174.          if ((abs(critters[index].x-centroid_x)+
  175.               abs(critters[index].y-centroid_y)) > 20)
  176.           {
  177.           critters[index].x+=critters[index].xv;
  178.           critters[index].y+=critters[index].yv;
  179.  
  180.           } // end if critter is far enough
  181.  
  182.          } // end for index
  183.  
  184. // END CONVERGENCE CODE //////////////////////////////////////////////////////
  185.  
  186.  
  187.      // scan under critters
  188.  
  189.      for (index=0; index<NUM_CRITTERS; index++)
  190.         critters[index].back=Read_Pixel_DB((int)critters[index].x,
  191.                                            (int)critters[index].y);
  192.  
  193.      // draw critters
  194.  
  195.      for (index=0; index<NUM_CRITTERS; index++)
  196.          Write_Pixel_DB((int)critters[index].x,
  197.                         (int)critters[index].y,10);
  198.  
  199.      // display double buffer
  200.  
  201.      Display_Double_Buffer(double_buffer,0);
  202.  
  203.      // lock onto 9 frames per second max
  204.  
  205.      Time_Delay(2);
  206.  
  207.      } // end while
  208.  
  209. // exit in a very cool way
  210.  
  211. Screen_Transition(SCREEN_SWIPE_X);
  212.  
  213. // free up all resources
  214.  
  215. Delete_Double_Buffer();
  216.  
  217. Set_Graphics_Mode(TEXT_MODE);
  218.  
  219. } // end main
  220.  
  221.