home *** CD-ROM | disk | FTP | other *** search
/ Aztec Shareware Collection / CHILDREN.ISO / firework / expgen.c < prev    next >
Text File  |  1990-01-30  |  15KB  |  513 lines

  1. /****************************************************************************
  2. * EXPGEN.C - Generates explosion data files for EXPLOD.C
  3. *
  4. * This program should be compilable with most C compilers.
  5. * To compile:
  6. *       Datalight C:   dlc expgen.c
  7. *       Turbo C:       tcc expgen.c
  8. *
  9. * The contents of this file is in the public domain.
  10. *
  11. * Change Log
  12. * 90/01/20 Dennis Lo         Verson 1.0 
  13. ****************************************************************************/
  14.  
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include "explod.h"
  18.  
  19. /*
  20.  * File format:
  21.  *  <num_points>
  22.  *  <num_frames>
  23.  *  <gravity>
  24.  *  <wind>
  25.  *  <trail length>
  26.  *  <x> <y>
  27.  *  <x> <y>
  28.  *  <x> <y>
  29.  *   ...
  30.  */
  31.  
  32. /* explosion parameters */
  33. int Num_points = 250;
  34. int Num_frames = 50;
  35. int Xsize = 200;
  36. int Ysize = 120;
  37. int Par1 = -1;
  38. int Par2 = -1;
  39. int Par3 = -1;
  40. int Gravity = 9;
  41. int Wind = 0;
  42. int Trail_length = 5;
  43. char Shape = '\0';
  44.  
  45. /*=====================================================================
  46.  * main
  47.  *=====================================================================
  48.  */
  49. main(argc, argv)
  50.     int argc;
  51.     char **argv;
  52. {
  53.     GetArgs(argc, argv);
  54.     srand (Par1 + Par2 + Xsize + Ysize + Num_points + Num_frames 
  55.         + Gravity + Wind + Trail_length);
  56.     switch (Shape)
  57.     {
  58.     case 'r':
  59.         PrintHeader();
  60.         if (Par1 == -1) Par1 = 0;  /* default no clumping */
  61.         if (Par2 == -1) Par2 = 8;  /* default clump size */
  62.         if (Par3 == -1) Par3 = 16; /* default clump spread size */
  63.         OvalGen (Num_points, Xsize, Ysize, Par1, Par2, Par3);
  64.         break;
  65.     case 'x':
  66.         PrintHeader();
  67.         DStarGen (Num_points, Xsize, Ysize, Par2);
  68.         break;
  69.     case '+':
  70.         PrintHeader();
  71.         HStarGen (Num_points, Xsize, Ysize, Par1);
  72.         break;
  73.     case 't':
  74.         PrintHeader();
  75.         TriangGen (Num_points, Xsize, Ysize, Par1, Par2);
  76.         break;
  77.     case 's':
  78.         PrintHeader();
  79.         TStarGen (Num_points, Xsize, Ysize, Par1, Par2);
  80.         break;
  81.     default:
  82.         printf ("No valid shape specified\n", Shape);
  83.         Instructions();
  84.         exit (1);
  85.     }
  86. }
  87.  
  88. /*=====================================================================
  89.  * Output the file header
  90.  *=====================================================================
  91.  */
  92. PrintHeader ()
  93. {
  94.     printf ("# EXPLOD DATA FILE\n");
  95.     printf ("%3d  # number of points\n", Num_points);
  96.     printf ("%3d  # number of frames\n", Num_frames);
  97.     printf ("%3d  # gravity\n", Gravity);
  98.     printf ("%3d  # wind\n", Wind);
  99.     printf ("%3d  # trail length\n", Trail_length);
  100. }
  101.  
  102. /*=====================================================================
  103.  * Process command line arguments.
  104.  *=====================================================================
  105.  */
  106. GetArgs (argc, argv)
  107.     int argc;
  108.     char *argv[];
  109. {
  110.     /*
  111.      * Loop to parse each command line parameter
  112.      */
  113.     while (--argc > 0) 
  114.     {
  115.         if (**++argv == '-') 
  116.         {
  117.             switch ((*argv)[1])
  118.             {
  119.         case 'a':        /* -a: Par 1 */
  120.             Par1 = atoi ((*argv) + 2);
  121.             break;
  122.         case 'b':        /* -b: Par 2 */
  123.             Par2 = atoi ((*argv) + 2);
  124.             break;
  125.         case 'c':        /* -c: Par 3 */
  126.             Par3 = atoi ((*argv) + 2);
  127.             break;
  128.                 case 'g':               /* -g: gravity (vert accel) */
  129.                     Gravity = atoi ((*argv) + 2);
  130.                     break;
  131.                 case 'w':               /* -w: wind (horiz accel) */
  132.                     Wind = atoi ((*argv) + 2);
  133.                     break;
  134.                 case 'x':               /* -x: explosion X size */
  135.                     Xsize = atoi ((*argv) + 2);
  136.                     break;
  137.                 case 'y':               /* -y: explosion Y size */
  138.             Ysize = atoi ((*argv) + 2);
  139.                     break;
  140.                 case 'p':               /* -p: # of explosion points */
  141.                     Num_points = atoi ((*argv) + 2);
  142.             if (Num_points > MAX_POINTS)
  143.             {
  144.             printf ("Maximum # of points is %d\n", MAX_POINTS);
  145.             exit (1);
  146.             }
  147.                     break;
  148.                 case 'f':               /* -f: # of frames */
  149.                     Num_frames = atoi ((*argv) + 2);
  150.             if (Num_frames > MAX_FRAMES)
  151.             {
  152.             printf ("Maximum # of frames is %d\n", MAX_FRAMES);
  153.             exit (1);
  154.             }
  155.                     break;
  156.                 case 't':               /* -t: trail length */
  157.                     Trail_length = atoi ((*argv) + 2);
  158.                     break;
  159.                 case 's':               /* -s[rsd]: shape */
  160.                     Shape = (*argv)[2];
  161.                     break;
  162.                 default:
  163.                     printf ("*** Invalid option: %s\n", *argv);
  164.                     Instructions();
  165.                     exit (1);
  166.             }
  167.         }
  168.     }
  169. }
  170.  
  171. /*=====================================================================
  172.  * Print instructions
  173.  *=====================================================================
  174.  */
  175. Instructions ()
  176. {
  177.     puts ("Usage: expgen [parameters] >output_file");
  178.     puts ("Parameters can be one of");
  179.     puts ("  -sC   :C = Explosion shape: r (round), + (star1), x (star2),");
  180.     puts ("             t (triangle), or s (star transformation). No default.");
  181.     puts ("  -xN   :N = Explosion X size.  Default: 200");
  182.     puts ("  -yN   :N = Explosion Y size.  Default: 120");
  183.     puts ("  -pN   :N = No. of points (max 300) Default: 250");
  184.     puts ("  -fN   :N = No. of frames (max 60) Default: 50");
  185.     puts ("  -tN   :N = Trail length.      Default: 5");
  186.     puts ("  -gN   :N = Gravity.           Default: 9");
  187.     puts ("  -wN   :N = Wind.              Default: 0");
  188.     puts ("  -aN   :N = Extra parameter 1.  Affects each shape differently.");
  189.     puts ("  -bN   :N = Extra parameter 2.  Affects each shape differently.");
  190.     puts ("  -cN   :N = Extra parameter 3.  Affects each shape differently.");
  191. }
  192.  
  193. /*====================================================================
  194.  * Return a random number between 1..maxval
  195.  *====================================================================
  196.  */
  197. int
  198. rnd (maxval)
  199. int maxval;
  200. {
  201. #   define MAX_RAND 32767       /* max value returned by rand() */
  202.     long l;
  203.  
  204.     l = (long) maxval * rand() / MAX_RAND;
  205.     return ((int) l);
  206. }
  207.  
  208. /*====================================================================
  209.  * Calculate/write the src & dest points for an oval explosion.
  210.  *====================================================================
  211.  */
  212. OvalGen (num_points, xsize, ysize, par1, par2, par3)
  213.     int num_points;
  214.     int xsize, ysize;
  215.     int par1;  /* 1 = clump */
  216.     int par2;  /* clump size */
  217.     int par3;  /* clump spread range */
  218. {
  219.     int dest_x, dest_y;
  220.     int src_x, src_y;
  221.     long x2 = (long) xsize * xsize;
  222.     long y2 = (long) ysize * ysize;
  223.     long x2y2 = (long) xsize * xsize * ysize * ysize;
  224.     int i = 0;
  225.     int j;
  226.     int par3div2 = par3 >> 1;
  227.     int par3div4 = par3 >> 2;
  228.  
  229.     src_x = 0;
  230.     src_y = 0;
  231.     for (i=0; i<num_points; i++) 
  232.     {
  233.         /* 
  234.          * Find a dest coordinates that is inside the ellipse with
  235.          * X radius of xsize and Y radius of ysize. */
  236.         while (1)
  237.         {
  238.             dest_x = rnd (2*xsize) - xsize;
  239.             dest_y = rnd (2*ysize) - ysize;
  240.  
  241.         /* Accept the point if it is within the oval */
  242.         if (y2 * dest_x * dest_x  +  x2 * dest_y * dest_y  <  x2y2)
  243.         break;
  244.         }
  245.     printf ("%d %d  %d %d\n", src_x, src_y, dest_x, dest_y);
  246.  
  247.      /* If -a1 then do clumping */
  248.     if (par1 == 1)
  249.     {
  250.         for (j=0; j<par2; j++)
  251.         printf ("%d %d  %d %d\n", src_x, src_y, 
  252.             dest_x + rnd(par3) - par3div2, 
  253.             dest_y + rnd(par3div2) - par3div4);
  254.         i += par2;
  255.     }
  256.     }
  257. }
  258.  
  259. /*====================================================================
  260.  * Calculate/write the src & dest points for a diagonal star explosion.
  261.  *====================================================================
  262.  */
  263. DStarGen (num_points, xsize, ysize, par1)
  264.     int num_points;
  265.     int xsize, ysize;
  266.     int par1;
  267. {
  268.     int dest_x, dest_y;
  269.     int src_x, src_y;
  270.     int i = 0;
  271.     long x2 = (long) xsize * xsize;
  272.     long y2 = (long) ysize * ysize;
  273.     long focus1;
  274.  
  275.     if (par1 == -1)
  276.         focus1 = x2 * y2 / 6;
  277.     else
  278.         focus1 = x2 * y2 / par1;
  279.  
  280.     for (i=0; i<num_points; i++) 
  281.     {
  282.         /* 
  283.          * Calculate src and dest coordinates.
  284.          * Select dest coordinate that is inside the hyperbolas with
  285.          * focii of xsize and ysize.
  286.          */
  287.         src_x = 0;
  288.         src_y = 0;
  289.         while (1)
  290.         {
  291.             dest_x = rnd (2*xsize) - xsize;
  292.             dest_y = rnd (2*ysize) - ysize;
  293.         if ((y2 * dest_x * dest_x  -  x2 * dest_y * dest_y  <  focus1)
  294.         &&  (x2 * dest_y * dest_y  -  y2 * dest_x * dest_x  <  focus1))
  295.         break;
  296.         }
  297.     printf ("%d %d  %d %d\n", src_x, src_y, dest_x, dest_y);
  298.     }
  299. }
  300.  
  301. /*====================================================================
  302.  * Calculate & write the points for a horiz star shaped explosion.
  303.  *====================================================================
  304.  */
  305. HStarGen (num_points, xsize, ysize, par1)
  306.     int num_points;
  307.     int xsize, ysize;
  308.     int par1;
  309. {
  310.     int dest_x, dest_y;
  311.     int src_x, src_y;
  312.     int i = 0;
  313.     long a;
  314.  
  315.     if (par1 == -1)
  316.         a = xsize * ysize / 10;
  317.     else
  318.         a = xsize * ysize / par1;
  319.  
  320.     for (i=0; i<num_points; i++) 
  321.     {
  322.         /* 
  323.          * Calculate src and dest coordinates.
  324.          * Select dest coordinate that is inside the hyperbolas with
  325.          * focii of xsize and ysize.
  326.          */
  327.         src_x = 0;
  328.         src_y = 0;
  329.         while (1)
  330.         {
  331.             dest_x = rnd (2*xsize) - xsize;
  332.             dest_y = rnd (2*ysize) - ysize;
  333.         if (dest_x > 0  &&  dest_y > 0  &&
  334.         dest_x * dest_y < a)
  335.         break;
  336.         if (dest_x > 0  &&  dest_y < 0  &&
  337.         dest_x * dest_y > -a)
  338.         break;
  339.         if (dest_x < 0  &&  dest_y > 0  &&
  340.         dest_x * dest_y > -a)
  341.         break;
  342.         if (dest_x < 0  &&  dest_y < 0  &&
  343.         dest_x * dest_y < a)
  344.         break;
  345.     }
  346.     printf ("%d %d  %d %d\n", src_x, src_y, dest_x, dest_y);
  347.     }
  348. }
  349.  
  350. /*====================================================================
  351.  * Calculate & write the points for a star transformation from a 
  352.  * diagonal star to a '+' shaped star.
  353.  *====================================================================
  354.  */
  355. TStarGen (num_points, xsize, ysize, par1, par2)
  356.     int num_points;
  357.     int xsize, ysize;
  358.     int par1;
  359.     int par2;
  360. {
  361.     int dest_x, dest_y;
  362.     int src_x, src_y;
  363.     int i = 0;
  364.     long a;
  365.  
  366.     int xsize2 = xsize>>1;
  367.     int ysize2 = ysize>>1;
  368.     long x2 = (long) xsize2 * xsize2;
  369.     long y2 = (long) ysize2 * ysize2;
  370.     long focus1;
  371.  
  372.     if (par1 == -1)
  373.         a = xsize * ysize / 10;
  374.     else
  375.         a = xsize * ysize / par1;
  376.  
  377.     if (par2 == -1)
  378.         focus1 = x2 * y2 / 6;
  379.     else
  380.         focus1 = x2 * y2 / par2;
  381.  
  382.     for (i=0; i<num_points; i++) 
  383.     {
  384.         /* 
  385.          * Calculate src and dest coordinates.
  386.          */
  387.         while (1)
  388.         {
  389.             src_x = rnd (2*xsize2) - xsize2;
  390.             src_y = rnd (2*ysize2) - ysize2;
  391.         if ((y2 * src_x * src_x  -  x2 * src_y * src_y  <  focus1)
  392.         &&  (x2 * src_y * src_y  -  y2 * src_x * src_x  <  focus1))
  393.         break;
  394.     }
  395.         while (1)
  396.         {
  397.             dest_x = rnd (2*xsize) - xsize;
  398.             dest_y = rnd (2*ysize) - ysize;
  399.         if (dest_x > 0  &&  dest_y > 0  &&
  400.         dest_x * dest_y < a)
  401.         break;
  402.         if (dest_x > 0  &&  dest_y < 0  &&
  403.         dest_x * dest_y > -a)
  404.         break;
  405.         if (dest_x < 0  &&  dest_y > 0  &&
  406.         dest_x * dest_y > -a)
  407.         break;
  408.         if (dest_x < 0  &&  dest_y < 0  &&
  409.         dest_x * dest_y < a)
  410.         break;
  411.     }
  412.     printf ("%d %d  %d %d\n", src_x, src_y, dest_x, dest_y);
  413.     }
  414. }
  415.  
  416.  
  417. /*====================================================================
  418.  * Calculate/write the src & dest points for an triangular explosion.
  419.  *====================================================================
  420.  */
  421. TriangGen (num_points, xsize, ysize, par1, par2)
  422.     int num_points;
  423.     int xsize, ysize;
  424.     int par1, par2;
  425. {
  426.     int dest_x, dest_y;
  427.     int src_x, src_y;
  428.     int x1;        /* upper vertex */
  429.     int y1;
  430.     int x2;        /* lower vertex */
  431.     int y2;
  432.     long y_intercept;    /* y_intercept of line between (x1,y1) and (x2,y2) */
  433.     int i = 0;
  434. int loop_count=0;
  435.  
  436. int invert = 0;
  437. if (xsize < 0) { xsize = -xsize; invert = 1; }
  438.  
  439.     /* 
  440.      * If not given as par1 and par2, then randomly select
  441.      * the 'bottom' and 'right' vertices of the triangle (the 
  442.      * left vertex is always (0,0).)
  443.      */
  444.     /* upper vertex */
  445.     y1 = ysize;
  446.     if (par1 == -1)
  447.         x1 = xsize/4 + rnd (xsize*3/4);
  448.     else
  449.     x1 = par1;
  450.  
  451.     /* lower vertex */
  452.     x2 = xsize;
  453.     if (par2 == -1)
  454.         y2 = ysize/4 + rnd (ysize*3/4);
  455.     else
  456.     y2 = par2;
  457.  
  458.     /* y-intercept = y - slope * x */
  459.     y_intercept = (long) y1 - ((long) x1 * (y2 - y1) / (x2 - x1));
  460.  
  461.     for (i=0; i<num_points; i++) 
  462.     {
  463.         src_x = xsize >> 1;
  464.         src_y = ysize >> 1;
  465.         /* 
  466.          * Calculate src and dest coordinates.
  467.          * Select dest coordinate that is inside the triangle defined by
  468.          * the following lines: 1. (0, 0) to (x1, y1)
  469.      *            2. (x2, y2) to (0, 0)
  470.      *            3. (x1, y1) to (x2, y2)
  471.      * Keep looping until a suitable point is found.
  472.          */
  473.         while (1)
  474.         {
  475.         /* Pick a random destination point */
  476.             dest_x = rnd (xsize);
  477.             dest_y = rnd (ysize);
  478.  
  479.         /*
  480.          * Accept the point only if it is within the triangle:
  481.          * 1. The slope of the line from (0, 0) to the point is < the 
  482.          *    slope of the line between (0, 0) and (x1, y1).
  483.          *    The proper expression is (dest_y/dest_x < y1/x1), but
  484.          *    in order to maintain precision, the equivalent expression
  485.          *    (dest_y < dest_x * y1/x1) is used instead.
  486.          * 2. The slope of the line between (0, 0) and the point is > the
  487.          *    slope of the line between (0, 0) and (x2, y2).
  488.          * 3. The point, when fitted into the equation y=mx+b of the line
  489.          *    between (x1, y1) and (x2, y2), results in y<mx+b.
  490.          */
  491.         if ( ((long) dest_y  <  (long) dest_x * y1 / x1)  &&
  492.           ((long) dest_y  >  (long) dest_x * y2 / x2)  &&
  493.          ((long) dest_y  <  
  494.            (long) dest_x * (y2 - y1) / (x2 - x1) + y_intercept))
  495.         break;
  496.         }
  497.  
  498.         /* Shift the point's origin so that (xsize/2, ysize/2) becomes (0,0) */
  499.     src_x -= xsize >> 1;
  500.     src_y -= ysize >> 1;
  501.     dest_x -= xsize >> 1;
  502.     dest_y -= ysize >> 1;
  503.  
  504.     if (invert) 
  505.     { 
  506.         src_x = -src_x; src_y = -src_y; 
  507.         dest_x = -dest_x; dest_y = -dest_y; 
  508.     }
  509.     printf ("%d %d  %d %d\n", src_x, src_y, dest_x, dest_y);
  510.     }
  511. }
  512.  
  513.