home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / qc / qc20 / grdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-15  |  18.1 KB  |  655 lines

  1. /* GRDEMO.C - Demonstrates capabilities of the QuickC graphics library.
  2.  * Uses MENU module to display menus. Uses TURTLE module for Turtle graphics.
  3.  */
  4.  
  5. #include <graph.h>
  6. #include <math.h>
  7. #include <malloc.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <conio.h>
  11. #include <time.h>
  12. #include "turtle.h"
  13. #include "menu.h"
  14.  
  15. /* Function prototypes */
  16. int  main( void );
  17. void Circles( void );
  18. void Sphere( void );
  19. int  Polygons( void );
  20. int  Spiral( int angle, double inc );
  21. int  InSpiral( double side, int angle, int inc );
  22. void Bug( void );
  23. void Adjust( void );
  24.  
  25. /* Returns a random number between min and max, which must be in
  26.  * integer range.
  27.  */
  28. #define getrandom( min, max ) ((rand() % (int)((max) - (min))) + (min) + 1)
  29.  
  30. /* Constants */
  31. #define PI      3.141593
  32. #define LASTATR 15
  33. #define NLASTATR 14
  34.  
  35. /* Array and enum for main menu */
  36. struct ITEM mnuMain[] =
  37. {               /* Highlight  Char  Pos */
  38.     0, "Quit",              /* Q     0  */
  39.     0, "Circles",           /* C     0  */
  40.     0, "Rotating Sphere",   /* R     0  */
  41.     0, "Tunnel",            /* T     0  */
  42.     0, "Spiral",            /* S     0  */
  43.     0, "Inverted Spiral",   /* I     0  */
  44.     0, "Bug",               /* B     0  */
  45.     0, "Adjust Window",     /* A     0  */
  46.     0, "Mode Change",       /* M     0  */
  47.     0, NULL
  48. };
  49.  
  50. /* Define constants (0, 1, 2,...) for menu choices */
  51. enum CHOICES
  52. {
  53.     QUIT, CIRCLES, SPHERE, TUNNEL, SPIRAL, INSPIRAL, BUG, ADJUST, CHANGE
  54. };
  55.  
  56. /* Arrays of video mode menu items and of corresponding mode numbers.
  57.  * Each has a temporary array containing all items, and a pointer version
  58.  * including all except Olivetti.
  59.  */
  60. struct ITEM mnuModesT[] =
  61. {               /* Highlight  Char  Pos */
  62.     0, "ORESCOLOR ",        /* O     0  */
  63.     4, "MRES4COLOR ",       /* 4     4  */
  64.     4, "MRESNOCOLOR",       /* N     4  */
  65.     4, "HRESBW",            /* B     4  */
  66.     0, "MRES16COLOR",       /* M     0  */
  67.     0, "HRES16COLOR",       /* H     0  */
  68.     0, "ERESCOLOR",         /* E     0  */
  69.     4, "VRES2COLOR",        /* 2     4  */
  70.     0, "VRES16COLOR",       /* V     0  */
  71.     1, "MRES256COLOR",      /* R     4  */
  72.     0, NULL
  73. };
  74. struct ITEM *mnuModes = &mnuModesT[1];  /* Default is no Olivetti mode */
  75.  
  76. int aModesT[] =
  77. {
  78.     _ORESCOLOR,
  79.     _MRES4COLOR,
  80.     _MRESNOCOLOR,
  81.     _HRESBW,
  82.     _MRES16COLOR,
  83.     _HRES16COLOR,
  84.     _ERESCOLOR,
  85.     _VRES2COLOR,
  86.     _VRES16COLOR,
  87.     _MRES256COLOR,
  88.     _TEXTMONO,
  89.     _ERESNOCOLOR,
  90.     _HERCMONO
  91. };
  92. int *aModes = &aModesT[1];              /* Default is no Olivetti mode */
  93.  
  94. /* Global video configuration */
  95. struct videoconfig vc;
  96.  
  97. int main()
  98. {
  99.     int rowMid, colMid;
  100.     int fColor, fFirstTime = TRUE;
  101.     int iMode, iMainCur = 0, iModesCur = 0;
  102.  
  103.     _displaycursor( _GCURSOROFF );
  104.     _getvideoconfig( &vc );
  105.     rowMid = vc.numtextrows / 2;
  106.     colMid = vc.numtextcols / 2;
  107.  
  108.     /* Select best graphics mode, adjust menus, set color flag. Note
  109.      * that this requires checking both the adapter and the mode.
  110.      */
  111.     switch( vc.adapter )
  112.     {
  113.         case _OCGA:
  114.             mnuModes = &mnuModesT[0];           /* Turn on Olivetti mode */
  115.             aModes = &aModesT[0];
  116.         case _CGA:
  117.             mnuModesT[4].achItem[0] = '\0';     /* Turn off EGA modes    */
  118.             iMode = _MRES4COLOR;
  119.             break;
  120.         case _HGC:
  121.             mnuModesT[7].achItem[0] = '\0';
  122.             iMode = _HERCMONO;
  123.             break;
  124.         case _OEGA:
  125.             mnuModes = &mnuModesT[0];           /* Turn on Olivetti mode */
  126.             aModes = &aModesT[0];
  127.         case _EGA:
  128.             mnuModesT[7].achItem[0] = '\0';     /* Turn off VGA modes    */
  129.             if( vc.memory > 64 )
  130.                 iMode = _ERESCOLOR;
  131.             else
  132.                 iMode = _HRES16COLOR;
  133.             break;
  134.         case _OVGA:
  135.             mnuModes = &mnuModesT[0];           /* Turn on Olivetti mode */
  136.             aModes = &aModesT[0];
  137.         case _VGA:
  138.             iMode = _VRES16COLOR;
  139.             break;
  140.         case _MCGA:
  141.             iMode = _MRES256COLOR;
  142.             break;
  143.         case _MDPA:
  144.         default:
  145.             puts( "No graphics mode available.\n" );
  146.             return TRUE;
  147.     }
  148.     switch( vc.mode )
  149.     {
  150.         case _TEXTBW80:
  151.         case _TEXTBW40:
  152.             fColor = FALSE;
  153.             break;
  154.         case _TEXTMONO:
  155.         case _ERESNOCOLOR:
  156.         case _HERCMONO:
  157.             fColor = FALSE;
  158.             if( iMode != _HERCMONO )
  159.                 iMode = _ERESNOCOLOR;
  160.             mnuMain[8].achItem[0] = '\0';       /* Turn off mode change */
  161.             break;
  162.         default:
  163.             fColor = TRUE;
  164.             break;
  165.     }
  166.  
  167.     /* Find current mode in mode array. */
  168.     for( iModesCur = 0; aModes[iModesCur] != iMode; iModesCur++ )
  169.         ;
  170.  
  171.     /* Seed randomizer with time. */
  172.     srand( (unsigned)time( NULL ) );
  173.  
  174.     while( TRUE )
  175.     {
  176.         /* Set text mode and optionally clear the screen to blue. */
  177.         _setvideomode(_DEFAULTMODE );
  178.         if( fColor )
  179.             _setbkcolor( (long)_TBLUE );
  180.         _clearscreen( _GCLEARSCREEN );
  181.  
  182.         /* Select from menu. */
  183.         iMainCur = Menu( rowMid, colMid, mnuMain, iMainCur );
  184.  
  185.         /* Set graphics mode and initialize turtle graphics. Put border
  186.          * on window.
  187.          */
  188.         if( iMainCur != CHANGE )
  189.         {
  190.             _setvideomode( iMode );
  191.             _displaycursor( _GCURSOROFF );
  192.             _getvideoconfig( &vc );
  193.             InitTurtle( &vc );
  194.             Rectangle( 2 * tc.xMax, 2 * tc.yMax );
  195.         }
  196.  
  197.         /* Branch to menu choice. */
  198.         switch( iMainCur )
  199.         {
  200.             case QUIT:
  201.                 _setvideomode( _DEFAULTMODE );
  202.                 return FALSE;
  203.             case CIRCLES:
  204.                 Circles();
  205.                 break;
  206.             case SPHERE:
  207.                 Sphere();
  208.                 break;
  209.             case TUNNEL:
  210.                 PenDown( FALSE );
  211.                 MoveTo( -tc.xMax * .2, tc.yMax * .15 );
  212.                 PenDown( TRUE );
  213.                 Polygons();
  214.                 while( !GetKey( NO_WAIT ) )
  215.                     NextColorValue( DEFAULT );   /* Rotate palette */
  216.                 break;
  217.             case SPIRAL:
  218.                 if( Spiral( getrandom( 30, 80 ), (double)getrandom( 1, 5 ) ) )
  219.                     break;
  220.                 while( !GetKey( NO_WAIT ) )
  221.                     NextColorValue( DEFAULT );
  222.                 break;
  223.             case INSPIRAL:
  224.                 NextColorIndex( 0 );
  225.                 if( InSpiral( (double)getrandom( 8, 20 ),
  226.                               getrandom( 4, 22 ),
  227.                               getrandom( 3, 31 ) ) )
  228.                     break;
  229.                 while( !GetKey( NO_WAIT ) )
  230.                     NextColorValue( DEFAULT );
  231.                 break;
  232.             case BUG:
  233.                 Bug();
  234.                 break;
  235.             case ADJUST:
  236.                 Adjust();
  237.                 continue;
  238.             case CHANGE:
  239.                 if( fColor )
  240.                     _setbkcolor( (long)_TBLUE );
  241.                 _clearscreen( _GCLEARSCREEN );
  242.  
  243.                 iModesCur = Menu( rowMid, colMid, mnuModes, iModesCur );
  244.                 iMode = aModes[iModesCur];
  245.                 if( vc.adapter == _MCGA )
  246.                     switch( iMode )
  247.                     {
  248.                         case _MRES16COLOR:
  249.                         case _HRES16COLOR:
  250.                         case _ERESCOLOR:
  251.                         case _VRES16COLOR:
  252.                             _settextposition( 1, 22 );
  253.                             _outtext( "Mode not recognized" );
  254.                             iMode = _MRES256COLOR;
  255.                     }
  256.                 break;
  257.         }
  258.     }
  259. }
  260.  
  261. /* Circles - Draw circles of varying sizes and colors on screen in a
  262.  * round pattern.
  263.  *
  264.  * Params: None
  265.  *
  266.  * Return: None
  267.  *
  268.  * Uses:   tc
  269.  */
  270. void Circles()
  271. {
  272.     double x, y, xyRadius;
  273.     int fFill, fPenDown;
  274.  
  275.     /* Initialize and save pen and fill flags. */
  276.     if( tc.cci <= 4 )
  277.         fFill = SetFill( FALSE );
  278.     else
  279.         fFill = SetFill( TRUE );
  280.     fPenDown = PenDown( FALSE );
  281.  
  282.     while( TRUE )
  283.     {
  284.         /* Draw circles. */
  285.         for( xyRadius = 10.0; xyRadius <= 130.0; xyRadius++ )
  286.         {
  287.             x = (tc.xMax - 30) * atan( sin( xyRadius / PI ) );
  288.             y = (tc.yMax - 30) * atan( cos( xyRadius / PI ) );
  289.             MoveTo( x, y );
  290.             PenColor( NextColorIndex( DEFAULT ) );
  291.             Circle( xyRadius );
  292.             if( GetKey( NO_WAIT ) )
  293.             {
  294.                 PenDown( fPenDown );
  295.                 SetFill( fFill );
  296.                 return;
  297.             }
  298.         }
  299.  
  300.         /* For palette modes (except 256 color), start over. */
  301.         if( tc.ccv == 64 || tc.ccv == 16 )
  302.         {
  303.             _clearscreen( _GCLEARSCREEN );
  304.             SetFill( FALSE );
  305.             MoveTo( 0.0, 0.0 );
  306.             PenColor( WHITE );
  307.             Rectangle( 2 * tc.xMax, 2 * tc.yMax );
  308.             SetFill( fFill );
  309.             NextColorValue( DEFAULT );
  310.         }
  311.     }
  312. }
  313.  
  314. /* Sphere - Draw and fill slices of a sphere. Rotate colors in EGA+ modes
  315.  * with more than 4 color indexes.
  316.  *
  317.  * Params: None
  318.  *
  319.  * Return: None
  320.  *
  321.  * Uses:   tc
  322.  */
  323. void Sphere()
  324. {
  325.     double xCur, xSize, ySize, xInc;
  326.     short ciBorder, fFill;
  327.     short cvi = 0, ci = 0, c = 0;
  328.     extern long cvlColors[];
  329.  
  330.     ySize = xSize = tc.yMax * 0.9 * 2;
  331.     fFill = SetFill( FALSE );
  332.     NextColorIndex( 0 );
  333.     xInc = xSize / 14;
  334.     ciBorder = PenColor( DEFAULT );
  335.     BorderColor( ciBorder );
  336.  
  337.     /* Draw slices. */
  338.     for( xCur = xInc; xCur <= xSize; xCur += xInc * 2 )
  339.         Ellipse( xCur, ySize );
  340.     SetFill( TRUE );
  341.     PenDown( FALSE );
  342.     Turn( 90 );
  343.     xSize /= 2;
  344.     MoveTo( xSize - xInc, 0.0 );
  345.  
  346.     NextColorValue( LIMITED );
  347.  
  348.     /* Fill slices. */
  349.     while( tc.xCur >= (-xSize + xInc))
  350.     {
  351.         PenColor( NextColorIndex( DEFAULT ) );
  352.         FillIn();
  353.         Move( -xInc );
  354.     }
  355.  
  356.     while( !GetKey( NO_WAIT ) )
  357.         NextColorValue( LIMITED );
  358.  
  359.     PenDown( TRUE );
  360.     SetFill( fFill );
  361. }
  362.  
  363. /* Polygons - Draws polygons (starting with triangle) of increasing
  364.  * size by incrementing the number of sides without changing the
  365.  * length of sides. Make sure pen is down.
  366.  *
  367.  * Params: None
  368.  *
  369.  * Return: 1 for user interrupt, 0 for edge of screen encountered
  370.  *
  371.  * Uses:   tc
  372.  */
  373. int Polygons()
  374. {
  375.     int cSides = 3, atrib = 1;
  376.     double dxy = tc.yUnit;
  377.  
  378.     while( TRUE )
  379.     {
  380.         PenColor( NextColorIndex( DEFAULT ) );
  381.         if( !Poly( cSides++, dxy += 1.5 ) )
  382.             return FALSE;
  383.         if( GetKey( NO_WAIT ) )
  384.             return TRUE;
  385.     }
  386. }
  387.  
  388. /* Spiral - Draw a spiral by incrementing the length of each side
  389.  * of a rotating figure.
  390.  *
  391.  * Params: ang - determines tightness
  392.  *         xyInc - determines size of sides
  393.  *
  394.  * Return: 1 for user interrupt, 0 for edge of screen encountered
  395.  *
  396.  * Uses:   tc
  397.  */
  398. int Spiral( int ang, double xyInc )
  399. {
  400.     double xy = tc.yUnit;
  401.  
  402.     while( TRUE )
  403.     {
  404.         PenColor( NextColorIndex( DEFAULT ) );
  405.         if( !Move( xy += xyInc ) )
  406.             return FALSE;
  407.         Turn( ang );
  408.         if( GetKey( NO_WAIT ) )
  409.             return TRUE;
  410.     }
  411. }
  412.  
  413. /* InSpiral - Draw an inverted spiral by increasing each angle
  414.  * of a rotating figure while keeping the length of sides constant.
  415.  *
  416.  * Params: xy - determines size
  417.  *         ang - initial angle determines shape
  418.  *         angInc - determines tightness and shape
  419.  *
  420.  * Return: 1 for user interrupt, 0 for edge of screen encountered
  421.  */
  422. int InSpiral( double xy, int ang, int angInc )
  423. {
  424.     while( TRUE )
  425.     {
  426.         PenColor( NextColorIndex( DEFAULT ) );
  427.         if( !Move( xy ) )
  428.             return FALSE;
  429.         Turn( ang += angInc );
  430.         if( GetKey( NO_WAIT ))
  431.             return TRUE;
  432.     }
  433. }
  434.  
  435. /* Bug - Draws a winged bug on the screen. Then moves it randomly
  436.  * around the screen.
  437.  *
  438.  * Params: None
  439.  *
  440.  * Return: None
  441.  *
  442.  * Uses:   tc
  443.  */
  444. void Bug()
  445. {
  446.  
  447.     static unsigned char uTopWing[] = { 0x81, 0x3c, 0xc3, 0x66,
  448.                                         0x66, 0x0f, 0xf0, 0x18 };
  449.     static unsigned char uBotWing[] = { 0x66, 0x0f, 0xf0, 0x18,
  450.                                         0x81, 0x3c, 0xc3, 0x66 };
  451.     char *buffer;               /* Buffer for image */
  452.  
  453.     /* Draw bug. */
  454.     PenDown( FALSE );
  455.     SetFill( TRUE );
  456.     Move( 40.0 );               /* Draw and fill front wings */
  457.     Turn( 90 );
  458.     Move( 80.0 );
  459.     PenColor( 1 );
  460.     _setfillmask( uTopWing );
  461.     Ellipse( 172.0, 70.0 );
  462.     Turn( 180 );
  463.     Move( 160.0 );
  464.     Ellipse( 172.0, 70.0 );
  465.     Turn(-90 );
  466.     MoveTo( 0.0, 0.0 );
  467.     Move( 25.0 );               /* Draw and fill back wings */
  468.     Turn( 90 );
  469.     Move( 70.0 );
  470.     PenColor( 2 );
  471.     _setfillmask( uBotWing );
  472.     Ellipse( 150.0, 70.0 );
  473.     Turn( 180 );
  474.     Move( 140.0 );
  475.     Ellipse( 150.0, 70.0 );
  476.     Turn(-90 );
  477.     MoveTo( 0.0, 0.0 );
  478.     _setfillmask( NULL );       /* Draw body */
  479.     PenColor( 3 );
  480.     BorderColor( 3 );
  481.     Ellipse( 52.0, 220.0 );
  482.     PenColor( 1 );              /* Drill eyes */
  483.     BorderColor( 1 );
  484.     SetFill( FALSE );
  485.     Move( 90.0 );
  486.     Turn( 90 );
  487.     Move( 22.0 );
  488.     Circle( 20.0 );
  489.     PenColor( 0 );
  490.     FillIn();
  491.     PenColor( 1 );
  492.     Turn( 180 );
  493.     Move( 44.0 );
  494.     Circle( 20.0 );
  495.     PenColor( 0 );
  496.     FillIn();
  497.  
  498.     /* Move into position - top-right of image. */
  499.     MoveTo( 0.0, 0.0 );
  500.     TurnTo( 0 );
  501.     Move( 120.0 );
  502.     Turn( -90 );
  503.     Move( 175.0 );
  504.     Turn( 90 );
  505.  
  506.     /* Size image and allocate memory for it. */
  507.     buffer = (char *)malloc( (size_t)ImageSize( 350.0, 240.0 ) );
  508.     GetImage( 350.0, 240.0, buffer );
  509.  
  510.     /* Move randomly, adjusting at edges. */
  511.     while( !GetKey( NO_WAIT ) )
  512.     {
  513.         if( tc.xCur <= (-tc.xMax + 15.0) )
  514.             TurnTo( 90 );
  515.         else if( tc.yCur <= (-tc.yMax + 15.0) )
  516.             TurnTo( 180 );
  517.         else if( tc.xCur >= (tc.xMax - 365.0) )
  518.             TurnTo( 270 );
  519.         else if( tc.yCur >= (tc.yMax - 255.0) )
  520.             TurnTo( 0 );
  521.         else
  522.             Turn( getrandom( -20, 20 ) );
  523.         Move( 3.0 );
  524.         PutImage( buffer, _GPSET );
  525.     }
  526.     free( (char *)buffer );
  527. }
  528.  
  529. /* Adjust - Allow the user to interactively adjust the display window.
  530.  * Unshifted direction keys adjust the window size. Shifted direction
  531.  * keys move the window. The numeric keypad plus and minus keys adjust
  532.  * aspect without changing the window. A window frame and a circle give
  533.  * visual feedback on adjustments.
  534.  *
  535.  * Params: None
  536.  *
  537.  * Return: None
  538.  *
  539.  * Uses:   tc and vc
  540.  */
  541. #define WININC 4
  542. void Adjust()
  543. {
  544.     short i;
  545.     double xyRadius = 400.0;
  546.     char achT[40];
  547.  
  548.     while( TRUE )
  549.     {
  550.         /* Display instructions. */
  551.         _settextposition( 2, 1 );
  552.         _outtext(" Grey PLUS and MINUS Adjust aspect\n" );
  553.         _outtext(" Cursor keys         Size window\n" );
  554.         _outtext(" SHIFT cursor keys   Move window\n" );
  555.         _outtext(" ENTER               Finished\n\n" );
  556.         sprintf( achT, "\n  ratio=%1.2f  xMax=%.f  yMax=%.f",
  557.                  tc.yxRatio, tc.xMax, tc.yMax );
  558.         _outtext( achT );
  559.         Rectangle( 2 * tc.xMax,  2 * tc.yMax );
  560.         PenDown( FALSE );
  561.  
  562.         /* Draw circle with cross. */
  563.         MoveTo( 75.0, 0.0 );
  564.         Circle( xyRadius );
  565.         for( i = 1; i <= 4; i++)
  566.         {
  567.             PenDown( TRUE );
  568.             Move( xyRadius );
  569.             Turn( 180 );
  570.             PenDown( FALSE );
  571.             Move( xyRadius );
  572.             Turn( 90 );
  573.         }
  574.  
  575.         switch( GetKey( CLEAR_WAIT ) )
  576.         {
  577.             /* Adjust aspect. */
  578.             case N_MINUS:
  579.                 tc.yxRatio = (tc.xMax - (WININC * tc.yUnit)) / tc.yMax;
  580.                 break;
  581.             case N_PLUS:
  582.                 tc.yxRatio = (tc.xMax + (WININC * tc.yUnit)) / tc.yMax;
  583.                 break;
  584.  
  585.             /* Adjust window size. */
  586.             case U_RT:
  587.                 if( tc.xsLeft < (vc.numxpixels / 3) )
  588.                     tc.xsLeft += WININC;
  589.                 if( tc.xsRight > (vc.numxpixels - (vc.numxpixels / 3)) )
  590.                     tc.xsRight -= WININC;
  591.                 break;
  592.             case U_LT:
  593.                 if( tc.xsLeft )
  594.                     tc.xsLeft -= WININC;
  595.                 if( tc.xsRight < vc.numxpixels )
  596.                     tc.xsRight += WININC;
  597.                 break;
  598.             case U_DN:
  599.                 if( tc.ysTop < (vc.numypixels / 3) )
  600.                     tc.ysTop += WININC;
  601.                 if( tc.ysBot > (vc.numypixels - (vc.numypixels / 3)) )
  602.                     tc.ysBot -= WININC;
  603.                 break;
  604.             case U_UP:
  605.                 if( tc.ysTop )
  606.                     tc.ysTop -= WININC;
  607.                 if( tc.ysBot < vc.numypixels )
  608.                     tc.ysBot += WININC;
  609.                 break;
  610.  
  611.             /* Adjust window position. */
  612.             case S_LT:
  613.                 if( tc.xsLeft )
  614.                 {
  615.                     tc.xsLeft -= WININC;
  616.                     tc.xsRight -= WININC;
  617.                 }
  618.                 break;
  619.             case S_RT:
  620.                 if( tc.xsRight < vc.numxpixels )
  621.                 {
  622.                     tc.xsLeft += WININC;
  623.                     tc.xsRight += WININC;
  624.                 }
  625.                 break;
  626.             case S_UP:
  627.                 if( tc.ysTop )
  628.                 {
  629.                     tc.ysTop -= WININC;
  630.                     tc.ysBot -= WININC;
  631.                 }
  632.                 break;
  633.             case S_DN:
  634.                 if( tc.ysBot < vc.numypixels )
  635.                 {
  636.                     tc.ysTop += WININC;
  637.                     tc.ysBot += WININC;
  638.                 }
  639.                 break;
  640.  
  641.             /* Finished. */
  642.             case ENTER:
  643.                 return;
  644.  
  645.             /* Ignore unknown key. */
  646.             default:
  647.                 Home( &vc );
  648.                 continue;
  649.         }
  650.         /* Clear screen and reset defaults after each adjustement. */
  651.         _clearscreen( _GCLEARSCREEN );
  652.         Home( &vc );
  653.     }
  654. }
  655.