home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_05 / rockdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-13  |  27.3 KB  |  1,219 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 stuff
  17. #include "graph4.h"
  18.  
  19. // D E F I N E S /////////////////////////////////////////////////////////////
  20.  
  21. // global clipping region default value
  22.  
  23. #define POLY_CLIP_MIN_X   0
  24. #define POLY_CLIP_MIN_Y   0
  25.  
  26. #define POLY_CLIP_MAX_X   319
  27. #define POLY_CLIP_MAX_Y   199
  28.  
  29. #define MAX_VERTICES      16   // maximum numbr of vertices in a polygon
  30.  
  31.  
  32.  
  33. #define NUM_ROCKS         10   // number of rocks in asteroid field
  34.  
  35. #define FRICTION          .2   // friction of space, yes believe it or not
  36.                                // space has friction to both energy and matter.
  37.                                // even in deepest space there are approx. 4
  38.                                // hydrogen atoms per cubic CM and the wave
  39.                                // impedence or energy friction is 377 ohms
  40.                                // that's why light maxes out at 186,300 MPS
  41.  
  42. // S T R U C T U R E S ///////////////////////////////////////////////////////
  43.  
  44. typedef struct vertex_typ
  45.         {
  46.  
  47.         float x,y;        // the vertex in 2-D
  48.  
  49.         } vertex, *vertex_ptr;
  50.  
  51. //////////////////////////////////////////////////////////////////////////////
  52.  
  53. // the polygon structure
  54.  
  55. typedef struct polygon_typ
  56.         {
  57.  
  58.         int b_color;                    // border color
  59.         int i_color;                    // interior color
  60.         int closed;                     // is the polygon closed
  61.         int filled;                     // is this polygon filled
  62.  
  63.         int lxo,lyo;                    // local origin of polygon
  64.         int num_vertices;               // number of defined vertices
  65.         vertex vertices[MAX_VERTICES];  // the vertices of the polygon
  66.  
  67.         } polygon, *polygon_ptr;
  68.  
  69. // a moving object
  70.  
  71. typedef struct object_typ
  72.         {
  73.         int state;          // state of rock
  74.  
  75.         int rotation_rate;  // angle to rotate object per frame
  76.  
  77.         int xv,yv;          // velocity vector
  78.  
  79.         polygon rock;       // one polygon per rock
  80.  
  81.         } object, *object_ptr;
  82.  
  83. // P R O T O T Y P E S ///////////////////////////////////////////////////////
  84.  
  85. void Bline(int xo, int yo, int x1,int y1, unsigned char color);
  86.  
  87. // G L O B A L S  ////////////////////////////////////////////////////////////
  88.  
  89. float sin_look[361],   // look up tables for sin and cosine
  90.       cos_look[361];
  91.  
  92. // the clipping region, set it to default on start up
  93.  
  94. int poly_clip_min_x = POLY_CLIP_MIN_X,
  95.     poly_clip_min_y = POLY_CLIP_MIN_Y,
  96.  
  97.     poly_clip_max_x = POLY_CLIP_MAX_X,
  98.     poly_clip_max_y = POLY_CLIP_MAX_Y;
  99.  
  100. // the asteroid field
  101.  
  102. object rocks[NUM_ROCKS];
  103.  
  104. // F U N C T I O N S /////////////////////////////////////////////////////////
  105.  
  106. void Create_Tables()
  107. {
  108. // this function creates the sin and cosine lookup tables
  109.  
  110. int index;
  111.  
  112. // create the tables
  113.  
  114. for (index=0; index<=360; index++)
  115.     {
  116.  
  117.     cos_look[index] = (float)cos((double)(index*3.14159/180));
  118.     sin_look[index] = (float)sin((double)(index*3.14159/180));
  119.  
  120.     } // end for
  121.  
  122. } // end Create_Tables
  123.  
  124. //////////////////////////////////////////////////////////////////////////////
  125.  
  126. void Rotate_Polygon(polygon_ptr poly, int angle)
  127. {
  128.  
  129. int index;    // loop index
  130.  
  131. float si,cs,  // values of sin and cosine
  132.       rx,ry;  // roated points
  133.  
  134. // rotate each point of the poly gon around its local origin
  135. // note that angle is an integer and ranges from -360 to +360
  136.  
  137. // compute sin and cos of angle to be rotated
  138.  
  139. if (angle>=0)
  140.    {
  141.    // extract sin and cosine from look up table
  142.  
  143.    si = sin_look[angle];
  144.    cs = cos_look[angle];
  145.  
  146.  
  147.    } // end if positive angle
  148. else
  149.    {
  150.    // angle is negative to convert to positive
  151.  
  152.    // convert negative angle to positive angle and extract values
  153.  
  154.    si = sin_look[angle+360];
  155.    cs = cos_look[angle+360];
  156.  
  157.    } // end else
  158.  
  159. // using values for sin and cosine rotate the point
  160.  
  161. for (index=0; index<poly->num_vertices; index++)
  162.     {
  163.     // compute rotated values using rotation eqns.
  164.  
  165.     rx  = poly->vertices[index].x * cs -  poly->vertices[index].y * si;
  166.     ry  = poly->vertices[index].y * cs +  poly->vertices[index].x * si;
  167.  
  168.     // store the rotated vertex back into structure
  169.  
  170.     poly->vertices[index].x = rx;
  171.     poly->vertices[index].y = ry;
  172.  
  173.     } // end for
  174.  
  175. } // end Rotate_Polygon
  176.  
  177. ///////////////////////////////////////////////////////////////////////////////
  178.  
  179. void Scale_Polygon(polygon_ptr poly, float scale)
  180. {
  181.  
  182. int index;
  183.  
  184. // scale each vertex of the polygon
  185.  
  186. for (index=0; index<poly->num_vertices; index++)
  187.     {
  188.     // multiply by the scaling factor
  189.  
  190.     poly->vertices[index].x*=scale;
  191.     poly->vertices[index].y*=scale;
  192.  
  193.     } // end for
  194.  
  195. } // end Scale_Polygon
  196.  
  197. ///////////////////////////////////////////////////////////////////////////////
  198.  
  199. void Translate_Polygon(polygon_ptr poly, int dx,int dy)
  200. {
  201.  
  202. // translate the origin of the polygon
  203.  
  204. poly->lxo+=dx;
  205. poly->lyo+=dy;
  206.  
  207. // that was easy!
  208.  
  209. } // end Translate_Polygon
  210.  
  211. ///////////////////////////////////////////////////////////////////////////////
  212.  
  213. void Draw_Polygon(polygon_ptr poly)
  214. {
  215. // this function draws a polygon on the screen without clipping
  216. // caller should make sure that vertices are within bounds of clipping
  217. // rectangle, also the polygon will always be unfilled regardless
  218. // of the fill flag
  219.  
  220. int index,xo,yo;
  221.  
  222. // extract local origin
  223.  
  224. xo = poly->lxo;
  225. yo = poly->lyo;
  226.  
  227. // draw polygon
  228.  
  229. for (index=0; index<poly->num_vertices-1; index++)
  230.     {
  231.  
  232.     Bline(xo+(int)poly->vertices[index].x,yo+(int)poly->vertices[index].y,
  233.           xo+(int)poly->vertices[index+1].x,yo+(int)poly->vertices[index+1].y,
  234.           poly->b_color);
  235.  
  236.     } // end for index
  237.  
  238.     // close polygon?
  239.  
  240.     if (!poly->closed)
  241.        return;
  242.  
  243.     Bline(xo+(int)poly->vertices[index].x,yo+(int)poly->vertices[index].y,
  244.           xo+(int)poly->vertices[0].x,yo+(int)poly->vertices[0].y,
  245.           poly->b_color);
  246.  
  247.  
  248. } // end Draw_Polygon
  249.  
  250. //////////////////////////////////////////////////////////////////////////////
  251.  
  252. int Clip_Line(int *x1,int *y1,int *x2, int *y2)
  253. {
  254. // this function clips the sent line using the globally defined clipping
  255. // region
  256.  
  257. int point_1 = 0, point_2 = 0;  // tracks if each end point is visible or invisible
  258.  
  259. int clip_always = 0;           // used for clipping override
  260.  
  261. int xi,yi;                     // point of intersection
  262.  
  263. int right_edge=0,              // which edges are the endpoints beyond
  264.     left_edge=0,
  265.     top_edge=0,
  266.     bottom_edge=0;
  267.  
  268.  
  269. int success = 0;               // was there a successfull clipping
  270.  
  271. float dx,dy;                   // used to holds slope deltas
  272.  
  273. // SECTION 1 //////////////////////////////////////////////////////////////////
  274.  
  275. // test if line is completely visible
  276.  
  277. if ( (*x1>=poly_clip_min_x) && (*x1<=poly_clip_max_x) &&
  278.      (*y1>=poly_clip_min_y) && (*y1<=poly_clip_max_y) )
  279.      point_1 = 1;
  280.  
  281.  
  282. if ( (*x2>=poly_clip_min_x) && (*x2<=poly_clip_max_x) &&
  283.      (*y2>=poly_clip_min_y) && (*y2<=poly_clip_max_y) )
  284.      point_2 = 1;
  285.  
  286. // SECTION 2 /////////////////////////////////////////////////////////////////
  287.  
  288. // test endpoints
  289.  
  290. if (point_1==1 && point_2==1)
  291.    return(1);
  292.  
  293. // SECTION 3 /////////////////////////////////////////////////////////////////
  294.  
  295. // test if line is completely invisible
  296.  
  297. if (point_1==0 && point_2==0)
  298.    {
  299.  
  300.    // must test to see if each endpoint is on the same side of one of
  301.    // the bounding planes created by each clipping region boundary
  302.  
  303.    if ( ((*x1<poly_clip_min_x) && (*x2<poly_clip_min_x)) || // to the left
  304.         ((*x1>poly_clip_max_x) && (*x2>poly_clip_max_x)) || // to the right
  305.  
  306.         ((*y1<poly_clip_min_y) && (*y2<poly_clip_min_y)) || // above
  307.         ((*y1>poly_clip_max_y) && (*y2>poly_clip_max_y)) )  // below
  308.         {
  309.  
  310.         // no need to draw line
  311.  
  312.         return(0);
  313.  
  314.         } // end if invisible
  315.  
  316.    // if we got here we have the special case where the line cuts into and
  317.    // out of the clipping region
  318.  
  319.    clip_always = 1;
  320.  
  321.    } // end if test for invisibly
  322.  
  323. // SECTION 4 /////////////////////////////////////////////////////////////////
  324.  
  325. // take care of case where either endpoint is in clipping region
  326.  
  327. if (( point_1==1) || (point_1==0 && point_2==0) )
  328.    {
  329.  
  330.    // compute deltas
  331.  
  332.    dx = *x2 - *x1;
  333.    dy = *y2 - *y1;
  334.  
  335.    // compute what boundary line need to be clipped against
  336.  
  337.    if (*x2 > poly_clip_max_x)
  338.       {
  339.       // flag right edge
  340.  
  341.       right_edge = 1;
  342.  
  343.       // compute intersection with right edge
  344.  
  345.       if (dx!=0)
  346.          yi = (int)(.5 + (dy/dx) * (poly_clip_max_x - *x1) + *y1);
  347.       else
  348.          yi = -1;  // invalidate intersection
  349.  
  350.       } // end if to right
  351.    else
  352.    if (*x2 < poly_clip_min_x)
  353.       {
  354.       // flag left edge
  355.  
  356.       left_edge = 1;
  357.  
  358.       // compute intersection with left edge
  359.  
  360.       if (dx!=0)
  361.          yi = (int)(.5 + (dy/dx) * (poly_clip_min_x - *x1) + *y1);
  362.       else
  363.          yi = -1;  // invalidate intersection
  364.  
  365.       } // end if to left
  366.  
  367.    // horizontal intersections
  368.  
  369.    if (*y2 > poly_clip_max_y)
  370.       {
  371.       // flag bottom edge
  372.  
  373.       bottom_edge = 1;
  374.  
  375.       // compute intersection with right edge
  376.  
  377.       if (dy!=0)
  378.          xi = (int)(.5 + (dx/dy) * (poly_clip_max_y - *y1) + *x1);
  379.       else
  380.          xi = -1;  // invalidate inntersection
  381.  
  382.       } // end if bottom
  383.    else
  384.    if (*y2 < poly_clip_min_y)
  385.       {
  386.       // flag top edge
  387.  
  388.       top_edge = 1;
  389.  
  390.       // compute intersection with top edge
  391.  
  392.       if (dy!=0)
  393.          xi = (int)(.5 + (dx/dy) * (poly_clip_min_y - *y1) + *x1);
  394.       else
  395.          xi = -1;  // invalidate inntersection
  396.  
  397.       } // end if top
  398.  
  399. // SECTION 5 /////////////////////////////////////////////////////////////////
  400.  
  401.    // now we know where the line passed thru
  402.    // compute which edge is the proper intersection
  403.  
  404.    if (right_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  405.       {
  406.  
  407.       *x2 = poly_clip_max_x;
  408.       *y2 = yi;
  409.  
  410.       success = 1;
  411.  
  412.       } // end if intersected right edge
  413.    else
  414.    if (left_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  415.       {
  416.  
  417.       *x2 = poly_clip_min_x;
  418.       *y2 = yi;
  419.  
  420.       success = 1;
  421.  
  422.       } // end if intersected left edge
  423.  
  424.    if (bottom_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  425.       {
  426.  
  427.       *x2 = xi;
  428.       *y2 = poly_clip_max_y;
  429.  
  430.       success = 1;
  431.  
  432.       } // end if intersected bottom edge
  433.    else
  434.    if (top_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  435.       {
  436.  
  437.       *x2 = xi;
  438.       *y2 = poly_clip_min_y;
  439.  
  440.       success = 1;
  441.  
  442.       } // end if intersected top edge
  443.  
  444.    } // end if point_1 is visible
  445.  
  446. // SECTION 6 /////////////////////////////////////////////////////////////////
  447.  
  448. // reset edge flags
  449.  
  450. right_edge = left_edge= top_edge = bottom_edge = 0;
  451.  
  452. // test second endpoint
  453.  
  454. if ( (point_2==1) || (point_1==0 && point_2==0))
  455.    {
  456.  
  457.    // compute deltas
  458.  
  459.    dx = *x1 - *x2;
  460.    dy = *y1 - *y2;
  461.  
  462.    // compute what boundary line need to be clipped against
  463.  
  464.    if (*x1 > poly_clip_max_x)
  465.       {
  466.       // flag right edge
  467.  
  468.       right_edge = 1;
  469.  
  470.       // compute intersection with right edge
  471.  
  472.       if (dx!=0)
  473.          yi = (int)(.5 + (dy/dx) * (poly_clip_max_x - *x2) + *y2);
  474.       else
  475.          yi = -1;  // invalidate inntersection
  476.  
  477.       } // end if to right
  478.    else
  479.    if (*x1 < poly_clip_min_x)
  480.       {
  481.       // flag left edge
  482.  
  483.       left_edge = 1;
  484.  
  485.       // compute intersection with left edge
  486.  
  487.       if (dx!=0)
  488.          yi = (int)(.5 + (dy/dx) * (poly_clip_min_x - *x2) + *y2);
  489.       else
  490.          yi = -1;  // invalidate intersection
  491.  
  492.       } // end if to left
  493.  
  494.    // horizontal intersections
  495.  
  496.    if (*y1 > poly_clip_max_y)
  497.       {
  498.       // flag bottom edge
  499.  
  500.       bottom_edge = 1;
  501.  
  502.       // compute intersection with right edge
  503.  
  504.       if (dy!=0)
  505.          xi = (int)(.5 + (dx/dy) * (poly_clip_max_y - *y2) + *x2);
  506.       else
  507.          xi = -1;  // invalidate inntersection
  508.  
  509.       } // end if bottom
  510.    else
  511.    if (*y1 < poly_clip_min_y)
  512.       {
  513.       // flag top edge
  514.  
  515.       top_edge = 1;
  516.  
  517.       // compute intersection with top edge
  518.  
  519.       if (dy!=0)
  520.          xi = (int)(.5 + (dx/dy) * (poly_clip_min_y - *y2) + *x2);
  521.       else
  522.          xi = -1;  // invalidate inntersection
  523.  
  524.       } // end if top
  525.  
  526.    // now we know where the line passed thru
  527.    // compute which edge is the proper intersection
  528.  
  529.    if (right_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  530.       {
  531.  
  532.       *x1 = poly_clip_max_x;
  533.       *y1 = yi;
  534.  
  535.       success = 1;
  536.  
  537.       } // end if intersected right edge
  538.    else
  539.    if (left_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  540.       {
  541.  
  542.       *x1 = poly_clip_min_x;
  543.       *y1 = yi;
  544.  
  545.       success = 1;
  546.  
  547.       } // end if intersected left edge
  548.  
  549.    if (bottom_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  550.       {
  551.  
  552.       *x1 = xi;
  553.       *y1 = poly_clip_max_y;
  554.  
  555.       success = 1;
  556.  
  557.       } // end if intersected bottom edge
  558.    else
  559.    if (top_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  560.       {
  561.  
  562.       *x1 = xi;
  563.       *y1 = poly_clip_min_y;
  564.  
  565.       success = 1;
  566.  
  567.       } // end if intersected top edge
  568.  
  569.  
  570.    } // end if point_2 is visible
  571.  
  572. // SECTION 7 /////////////////////////////////////////////////////////////////
  573.  
  574. return(success);
  575.  
  576. } // end Clip_Line
  577.  
  578. //////////////////////////////////////////////////////////////////////////////
  579.  
  580. void Draw_Polygon_Clip(polygon_ptr poly)
  581. {
  582.  
  583. // this function draws a polygon on the screen with clipping
  584. // also the polygon will always be unfilled regardless
  585. // of the fill flag in the polygon structure
  586.  
  587. int index,  // loop index
  588.     xo,yo,  // local origin
  589.     x1,y1,  // end points of current line being processed
  590.     x2,y2;
  591.  
  592. // extract local origin
  593.  
  594. xo = poly->lxo;
  595. yo = poly->lyo;
  596.  
  597. // draw polygon
  598.  
  599. for (index=0; index<poly->num_vertices-1; index++)
  600.     {
  601.  
  602.     // extract the line
  603.  
  604.     x1 = (int)poly->vertices[index].x+xo;
  605.     y1 = (int)poly->vertices[index].y+yo;
  606.  
  607.     x2 = (int)poly->vertices[index+1].x+xo;
  608.     y2 = (int)poly->vertices[index+1].y+yo;
  609.  
  610.     // clip line to viewing screen and draw unless line is totally invisible
  611.  
  612.     if (Clip_Line(&x1,&y1,&x2,&y2))
  613.        {
  614.        // line was clipped and now can be drawn
  615.        Bline(x1,y1,x2,y2,poly->b_color);
  616.  
  617.        } // end if draw line
  618.  
  619.     } // end for index
  620.  
  621.     // close polygon?        // close polygon
  622.  
  623.     if (!poly->closed)
  624.        return;
  625.  
  626.     // extract the line
  627.  
  628.     x1 = (int)poly->vertices[index].x+xo;
  629.     y1 = (int)poly->vertices[index].y+yo;
  630.  
  631.     x2 = (int)poly->vertices[0].x+xo;
  632.     y2 = (int)poly->vertices[0].y+yo;
  633.  
  634.     // clip line to viewing screen and draw unless line is totally invisible
  635.  
  636.     if (Clip_Line(&x1,&y1,&x2,&y2))
  637.        {
  638.  
  639.        // line was clipped and now can be drawn
  640.  
  641.        Bline(x1,y1,x2,y2,poly->b_color);
  642.  
  643.        } // end if draw line
  644.  
  645. } // end Draw_Polygon_Clip
  646.  
  647. //////////////////////////////////////////////////////////////////////////////
  648.  
  649. void Bline(int xo, int yo, int x1,int y1, unsigned char color)
  650. {
  651. // this function uses Bresenham's algorithm IBM (1965) to draw a line from
  652. // (xo,yo) - (x1,y1)
  653.  
  654. int dx,             // difference in x's
  655.     dy,             // difference in y's
  656.     x_inc,          // amount in pixel space to move during drawing
  657.     y_inc,          // amount in pixel space to move during drawing
  658.     error=0,        // the discriminant i.e. error i.e. decision variable
  659.     index;          // used for looping
  660.  
  661.  
  662.  
  663. unsigned char far *vb_start = video_buffer; // directly access the video
  664.                                             // buffer for speed
  665.  
  666.  
  667. // SECTION 1 /////////////////////////////////////////////////////////////////
  668.  
  669. // pre-compute first pixel address in video buffer
  670. // use shifts for multiplication
  671.  
  672.  
  673. vb_start = vb_start + ((unsigned int)yo<<6) +
  674.                       ((unsigned int)yo<<8) +
  675.                       (unsigned int)xo;
  676.  
  677. // compute deltas
  678.  
  679. dx = x1-xo;
  680. dy = y1-yo;
  681.  
  682. // SECTION 2 /////////////////////////////////////////////////////////////////
  683.  
  684. // test which direction the line is going in i.e. slope angle
  685.  
  686. if (dx>=0)
  687.    {
  688.    x_inc = 1;
  689.  
  690.    } // end if line is moving right
  691. else
  692.    {
  693.    x_inc = -1;
  694.    dx    = -dx;  // need absolute value
  695.  
  696.    } // end else moving left
  697.  
  698. // SECTION 3 /////////////////////////////////////////////////////////////////
  699.  
  700. // test y component of slope
  701.  
  702. if (dy>=0)
  703.    {
  704.    y_inc = 320; // 320 bytes per line
  705.  
  706.    } // end if line is moving down
  707. else
  708.    {
  709.    y_inc = -320;
  710.    dy    = -dy;  // need absolute value
  711.  
  712.    } // end else moving up
  713.  
  714. // SECTION 4 /////////////////////////////////////////////////////////////////
  715.  
  716. // now based on which delta is greater we can draw the line
  717.  
  718. if (dx>dy)
  719.    {
  720.  
  721.    // draw the line
  722.  
  723.    for (index=0; index<=dx; index++)
  724.        {
  725.        // set the pixel
  726.  
  727.        *vb_start = color;
  728.  
  729.        // adjust the discriminate
  730.  
  731.        error+=dy;
  732.  
  733.        // test if error overflowed
  734.  
  735.        if (error>dx)
  736.           {
  737.  
  738.           error-=dx;
  739.  
  740.           // move to next line
  741.  
  742.           vb_start+=y_inc;
  743.  
  744.           } // end if error overflowed
  745.  
  746.        // move to the next pixel
  747.  
  748.        vb_start+=x_inc;
  749.  
  750.        } // end for
  751.  
  752.    } // end if |slope| <= 1
  753. else
  754.    {
  755.  
  756. // SECTION 5 /////////////////////////////////////////////////////////////////
  757.  
  758.    // draw the line
  759.  
  760.    for (index=0; index<=dy; index++)
  761.        {
  762.        // set the pixel
  763.  
  764.        *vb_start = color;
  765.  
  766.        // adjust the discriminate
  767.  
  768.        error+=dx;
  769.  
  770.        // test if error overflowed
  771.  
  772.        if (error>0)
  773.           {
  774.  
  775.           error-=dy;
  776.  
  777.           // move to next line
  778.  
  779.           vb_start+=x_inc;
  780.  
  781.           } // end if error overflowed
  782.  
  783.        // move to the next pixel
  784.  
  785.        vb_start+=y_inc;
  786.  
  787.        } // end for
  788.  
  789.    } // end else |slope| > 1
  790.  
  791. } // end Bline
  792.  
  793. ///////////////////////////////////////////////////////////////////////////////
  794.  
  795. void Draw_Boundary(int color)
  796. {
  797. // draws in the clipping boundary if user is intersted in seeing it
  798.  
  799. Bline(poly_clip_min_x,poly_clip_min_y,
  800.       poly_clip_max_x,poly_clip_min_y,color);
  801.  
  802.  
  803. Bline(poly_clip_max_x,poly_clip_min_y,
  804.       poly_clip_max_x,poly_clip_max_y,color);
  805.  
  806. Bline(poly_clip_max_x,poly_clip_max_y,
  807.       poly_clip_min_x,poly_clip_max_y,color);
  808.  
  809. Bline(poly_clip_min_x,poly_clip_max_y,
  810.       poly_clip_min_x,poly_clip_min_y,color);
  811.  
  812. } // end Draw_Boundary
  813.  
  814. //////////////////////////////////////////////////////////////////////////////
  815.  
  816. void Initialize_Rocks(void)
  817. {
  818.  
  819. // this function initializes all the rocks in the asteroid field
  820.  
  821. int index;      // loop index
  822.  
  823. float scale;    // used to change scale of each rock
  824.  
  825. // initialize all rocks in asteroid field
  826.  
  827. for (index=0; index<NUM_ROCKS; index++)
  828.     {
  829.  
  830.     // build up each rock and add a little noise to each vertex
  831.     // to make them look different
  832.  
  833.     rocks[index].rock.vertices[0].x = 4.0 + rand()%2;
  834.     rocks[index].rock.vertices[0].y = 4   + rand()%2;
  835.     rocks[index].rock.vertices[1].x = 9   + rand()%2;
  836.     rocks[index].rock.vertices[1].y = -3  - rand()%2;
  837.     rocks[index].rock.vertices[2].x = 6   + rand()%2;
  838.     rocks[index].rock.vertices[2].y = -5  - rand()%2;
  839.     rocks[index].rock.vertices[3].x = 2   + rand()%2;
  840.     rocks[index].rock.vertices[3].y = -3  - rand()%2;
  841.     rocks[index].rock.vertices[4].x = -4  - rand()%2;
  842.     rocks[index].rock.vertices[4].y = -6  - rand()%2;
  843.     rocks[index].rock.vertices[5].x = -3  - rand()%2;
  844.     rocks[index].rock.vertices[5].y = 5   + rand()%2;
  845.  
  846.     // set number of vertices
  847.  
  848.     rocks[index].rock.num_vertices = 6;
  849.  
  850.     rocks[index].rock.b_color      = 10;
  851.     rocks[index].rock.i_color      = 10;
  852.     rocks[index].rock.closed       = 1;
  853.     rocks[index].rock.filled       = 0;
  854.     rocks[index].rock.lxo          = rand()%poly_clip_max_x;
  855.     rocks[index].rock.lyo          = rand()%poly_clip_max_y;
  856.  
  857.     // compute velocity
  858.  
  859.     rocks[index].xv = -5 + rand()%10;
  860.     rocks[index].yv = -5 + rand()%10;
  861.  
  862.     // set state of rock to alive and set rotation rate
  863.  
  864.     rocks[index].state = 1;
  865.  
  866.     rocks[index].rotation_rate = -10 + rand() % 20;
  867.  
  868.     // compute scale
  869.  
  870.     scale = ((float)(5 + rand()%15))/10;
  871.  
  872.     // scale the rock to make it look different
  873.  
  874.     Scale_Polygon((polygon_ptr)&rocks[index].rock,scale);
  875.  
  876.     } // end for index
  877.  
  878. } // end Initialize_Rocks
  879.  
  880. //////////////////////////////////////////////////////////////////////////////
  881.  
  882. void Draw_Rocks(void)
  883. {
  884. // this function draws all the asteroids
  885.  
  886. int index;  // loop variable
  887.  
  888. // loop thru all rocks and draw them
  889.  
  890. for (index=0; index<NUM_ROCKS; index++)
  891.     {
  892.  
  893.     rocks[index].rock.b_color = 10;
  894.     Draw_Polygon_Clip((polygon_ptr)&rocks[index].rock);
  895.  
  896.     } // end for
  897.  
  898. } // end Draw_Rocks
  899.  
  900. //////////////////////////////////////////////////////////////////////////////
  901.  
  902. void Erase_Rocks(void)
  903. {
  904. // this functions erases all the asteroids
  905.  
  906. int index;  // loop variable
  907.  
  908. // loop thru all rocks and draw them
  909.  
  910. for (index=0; index<NUM_ROCKS; index++)
  911.     {
  912.  
  913.     rocks[index].rock.b_color = 0;
  914.     Draw_Polygon_Clip((polygon_ptr)&rocks[index].rock);
  915.  
  916.     } // end for
  917.  
  918. } // end Erase_Rocks
  919.  
  920. //////////////////////////////////////////////////////////////////////////////
  921.  
  922. void Move_Rocks(void)
  923. {
  924.  
  925. // this funnction moves and rotates all the asteroids
  926.  
  927. int index;  // loop variable
  928.  
  929. // loop thru all rocks and draw them
  930.  
  931. for (index=0; index<NUM_ROCKS; index++)
  932.     {
  933.  
  934.     // translate the polygon
  935.  
  936.     Translate_Polygon((polygon_ptr)&rocks[index].rock,
  937.                       rocks[index].xv,rocks[index].yv);
  938.  
  939.     // rotate the rock
  940.  
  941.     Rotate_Polygon((polygon_ptr)&rocks[index].rock,rocks[index].rotation_rate);
  942.  
  943.     // test for collsion of edges
  944.  
  945.     if (rocks[index].rock.lxo > 310)
  946.         rocks[index].rock.lxo = 10;
  947.     else
  948.     if (rocks[index].rock.lxo < 10)
  949.         rocks[index].rock.lxo = 310;
  950.  
  951.     if (rocks[index].rock.lyo > 190)
  952.         rocks[index].rock.lyo = 10;
  953.     else
  954.     if (rocks[index].rock.lyo < 10)
  955.         rocks[index].rock.lyo = 190;
  956.  
  957.     } // end for
  958.  
  959. } // end Move_Rocks
  960.  
  961. // M A I N ///////////////////////////////////////////////////////////////////
  962.  
  963. void main(void)
  964. {
  965.  
  966. int done=0;           // system exit flag
  967.  
  968. polygon ship;
  969.  
  970. float xv=0,           // initial velocity of ship
  971.       yv=0;
  972.  
  973. int   angle=90,       // initial angle of ship
  974.       engines=0;      // tracks if engines are on
  975.  
  976. // SECTION 1 /////////////////////////////////////////////////////////////////
  977.  
  978. // set video mode to 320x200 256 color mode
  979.  
  980. Set_Video_Mode(VGA256);
  981.  
  982. // create lookup tables for polygon engine
  983.  
  984. Create_Tables();
  985.  
  986. // SECTION 2 /////////////////////////////////////////////////////////////////
  987.  
  988. // build up a little spaceship polygon
  989.  
  990. ship.vertices[0].x = 3;
  991. ship.vertices[0].y = -19;
  992.  
  993. ship.vertices[1].x = 12;
  994. ship.vertices[1].y = -1;
  995.  
  996. ship.vertices[2].x = 17;
  997. ship.vertices[2].y = 2;
  998.  
  999. ship.vertices[3].x = 17;
  1000. ship.vertices[3].y = 9;
  1001.  
  1002. ship.vertices[4].x = 8;
  1003. ship.vertices[4].y = 14;
  1004.  
  1005. ship.vertices[5].x = 5;
  1006. ship.vertices[5].y = 8;
  1007.  
  1008. ship.vertices[6].x = -5;
  1009. ship.vertices[6].y = 8;
  1010.  
  1011. ship.vertices[7].x = -8;
  1012. ship.vertices[7].y = 14;
  1013.  
  1014. ship.vertices[8].x = -17;
  1015. ship.vertices[8].y = 9;
  1016.  
  1017. ship.vertices[9].x = -17;
  1018. ship.vertices[9].y = 2;
  1019.  
  1020. ship.vertices[10].x = -12;
  1021. ship.vertices[10].y = -1;
  1022.  
  1023. ship.vertices[11].x = -3;
  1024. ship.vertices[11].y = -19;
  1025.  
  1026. ship.vertices[12].x = -3;
  1027. ship.vertices[12].y = -8;
  1028.  
  1029. ship.vertices[13].x = 3;
  1030. ship.vertices[13].y = -8;
  1031.  
  1032. // set position of shaceship
  1033.  
  1034. ship.lxo = 160;
  1035. ship.lyo = 100;
  1036.  
  1037. // fill in important fields
  1038.  
  1039. ship.num_vertices = 14;
  1040. ship.b_color      = 1;
  1041. ship.closed       = 1;
  1042.  
  1043. // make the ship a little smaller
  1044.  
  1045. Scale_Polygon((polygon_ptr)&ship,0.75);
  1046.  
  1047. // create the asteroid field
  1048.  
  1049. Initialize_Rocks();
  1050.  
  1051. // main event loop
  1052.  
  1053. // SECTION 3 /////////////////////////////////////////////////////////////////
  1054.  
  1055. while(!done)
  1056.      {
  1057.      // erase all the rocks
  1058.  
  1059.      Erase_Rocks();
  1060.  
  1061.      // erase the players ship
  1062.  
  1063.      ship.b_color = 0;
  1064.  
  1065.      Draw_Polygon_Clip((polygon_ptr)&ship);
  1066.  
  1067.      // move everything
  1068.  
  1069.      engines=0;
  1070.  
  1071. // SECTION 4 /////////////////////////////////////////////////////////////////
  1072.  
  1073.      if (kbhit())
  1074.         {
  1075.  
  1076.         // get the key
  1077.  
  1078.         switch(getch())
  1079.               {
  1080.  
  1081.               case 's':
  1082.                  {
  1083.  
  1084.                  Rotate_Polygon((polygon_ptr)&ship,5);
  1085.  
  1086.                  // adjust angle
  1087.  
  1088.                  angle+=5;
  1089.  
  1090.                  if (angle>360)
  1091.                      angle=0;
  1092.  
  1093.                  } break;
  1094.  
  1095.               case 'a':
  1096.                  {
  1097.  
  1098.                  Rotate_Polygon((polygon_ptr)&ship,-5);
  1099.  
  1100.                  // adjust angle
  1101.  
  1102.                  angle-=5;
  1103.  
  1104.                  if (angle<0)
  1105.                      angle=360;
  1106.  
  1107.                  } break;
  1108.  
  1109.               case 'l':
  1110.                  {
  1111.  
  1112.                  // adjust velocity vector based on direction
  1113.  
  1114.                  xv = xv - cos(angle*3.14159/180);
  1115.                  yv = yv - sin(angle*3.14159/180);
  1116.  
  1117.                  // flag that engines are on
  1118.  
  1119.                  engines = 1;
  1120.  
  1121.                  // control upper throttle limit
  1122.  
  1123.                  if (xv>10)
  1124.                      xv=10;
  1125.                  else
  1126.                  if (xv<-10)
  1127.                      xv=-10;
  1128.  
  1129.                  if (yv>10)
  1130.                      yv=10;
  1131.                  else
  1132.                  if (yv<-10)
  1133.                      yv=-10;
  1134.  
  1135.                  } break;
  1136.  
  1137.               case 'q':     // user trying to exit
  1138.                  {
  1139.                  done=1;
  1140.                  } break;
  1141.  
  1142.               } // end switch
  1143.  
  1144.         } // end if kbhit
  1145.  
  1146. // SECTION 5 /////////////////////////////////////////////////////////////////
  1147.  
  1148.      // decelerate engines if they are off
  1149.  
  1150.      if (!engines)
  1151.         {
  1152.  
  1153.         // tend x and y components of velocity toward 0.
  1154.  
  1155.         if (xv>0)
  1156.            xv-=FRICTION;
  1157.         else
  1158.         if (xv<0)
  1159.            xv+=FRICTION;
  1160.  
  1161.         if (yv>0)
  1162.            yv-=FRICTION;
  1163.         else
  1164.         if (yv<0)
  1165.            yv+=FRICTION;
  1166.  
  1167.         } // end if
  1168.  
  1169.      // test if ship went off screen
  1170.  
  1171.      if (ship.lxo > 310)
  1172.          ship.lxo = 10;
  1173.      else
  1174.      if (ship.lxo < 10)
  1175.          ship.lxo = 310;
  1176.  
  1177.      if (ship.lyo > 190)
  1178.          ship.lyo = 10;
  1179.      else
  1180.      if (ship.lyo < 10)
  1181.          ship.lyo = 190;
  1182.  
  1183. // SECTION 6 /////////////////////////////////////////////////////////////////
  1184.  
  1185.      // do the actual translation
  1186.  
  1187.      Translate_Polygon((polygon_ptr)&ship,xv,yv);
  1188.  
  1189.      // now move the rocks
  1190.  
  1191.      Move_Rocks();
  1192.  
  1193. // SECTION 7 /////////////////////////////////////////////////////////////////
  1194.  
  1195.      // Draw everything
  1196.  
  1197.      Draw_Rocks();
  1198.  
  1199.      ship.b_color = 9;
  1200.  
  1201.      Draw_Polygon_Clip((polygon_ptr)&ship);
  1202.  
  1203.      // draw instructions
  1204.  
  1205.      Blit_String(0,190,15,"(A,S)-Rotate, (L)-Thrust, (Q)-Exit",1);
  1206.  
  1207.      // just chill here for 1/18.2 th of a second
  1208.  
  1209.      Delay(1);
  1210.  
  1211.      } // end while
  1212.  
  1213. // reset the video mode back to text
  1214.  
  1215. Set_Video_Mode(TEXT_MODE);
  1216.  
  1217. } // end main
  1218.  
  1219.