home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / gdidemo / bounce.c next >
C/C++ Source or Header  |  1997-10-05  |  15KB  |  617 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. /*---------------------------------------------------------------------------*\
  13. | BOUNCING BALL MODULE
  14. \*---------------------------------------------------------------------------*/
  15.  
  16. #include <windows.h>
  17. #include "gdidemo.h"
  18. #include "bounce.h"
  19.  
  20.  
  21. VOID XFormClear(PMYXFORM);
  22. VOID XFormScale(PMYXFORM,int,int);
  23. VOID XFormTrans(PMYXFORM,int,int);
  24. VOID XFormPoint(PMYXFORM,LPPOINT);
  25.  
  26.  
  27. /*---------------------------------------------------------------------------*\
  28. | CREATE BOUNCE WINDOW PROCEDURE
  29. |
  30. \*---------------------------------------------------------------------------*/
  31. HWND FAR CreateBounceWindow(HWND hWndClient, int nItem)
  32. {
  33.     HANDLE          hInstance;
  34.     MDICREATESTRUCT mcs;
  35.     static char buffer[256];
  36.  
  37.  
  38.     hInstance = GETINSTANCE(hWndClient);
  39.     LoadString (hInstance, BOUNCETITLE, buffer, 256);
  40.  
  41.     /*
  42.     ** Initialize the MDI create struct for creation of the
  43.     ** test window.
  44.     */
  45.     mcs.szClass = BOUNCECLASS;
  46.     mcs.szTitle = buffer;
  47.     mcs.hOwner  = hInstance;
  48.     mcs.x       = CW_USEDEFAULT;
  49.     mcs.y       = CW_USEDEFAULT;
  50.     mcs.cx      = CW_USEDEFAULT;
  51.     mcs.cy      = CW_USEDEFAULT;
  52.     mcs.style   = 0l;
  53.     mcs.lParam  = (LONG)nItem;
  54.  
  55.     return((HWND)SendMessage(hWndClient,WM_MDICREATE,0,(LONG)(LPMDICREATESTRUCT)&mcs));
  56. }
  57.  
  58.  
  59. /*---------------------------------------------------------------------------*\
  60. | BOUNCE WINDOW PROCEDURE
  61. |
  62. \*---------------------------------------------------------------------------*/
  63. LONG APIENTRY BounceProc(HWND hWnd, UINT wMsg, WPARAM wParam, LONG lParam)
  64. {
  65.     switch(wMsg)
  66.     {
  67.         case WM_CREATE:
  68.             BounceCreateProc(hWnd);
  69.             break;
  70.  
  71.         case WM_MOVE:
  72.             BounceRefresh(hWnd);
  73.             break;
  74.  
  75.         case WM_COMMAND:
  76.             BounceCommandProc(hWnd,wParam,lParam);
  77.             break;
  78.  
  79.         case WM_TIMER:
  80.             BounceObjects(hWnd);
  81.             break;
  82.  
  83.         case WM_PAINT:
  84.             BouncePaintProc(hWnd);
  85.             break;
  86.  
  87.         case WM_DESTROY:
  88.             BounceDestroyProc(hWnd);
  89.             break;
  90.  
  91.  
  92.         default:
  93.             return(DefMDIChildProc(hWnd,wMsg,wParam,lParam));
  94.     }
  95.     return(0l);
  96. }
  97.  
  98.  
  99. /*---------------------------------------------------------------------------*\
  100. | BOUNCE CREATE PROCEDURE
  101. |
  102. \*---------------------------------------------------------------------------*/
  103. BOOL BounceCreateProc(HWND hWnd)
  104. {
  105.     PBOUNCEDATA pbd;
  106.  
  107.  
  108.     if(AllocWindowInfo(hWnd,sizeof(BOUNCEDATA)))
  109.     {
  110.         if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
  111.         {
  112.             pbd->hBall1 = ballCreate(hWnd,20,20,RGB(255,0,0));
  113.             pbd->hBall2 = ballCreate(hWnd,20,20,RGB(0,0,255));
  114.             pbd->hBall3 = ballCreate(hWnd,20,20,RGB(0,255,0));
  115.             pbd->hBall4 = ballCreate(hWnd,20,20,RGB(255,0,255));
  116.  
  117.             UnlockWindowInfo(hWnd);
  118.  
  119.             SetTimer(hWnd,1,50,NULL);
  120.             return(TRUE);
  121.         }
  122.         FreeWindowInfo(hWnd);
  123.     }
  124.     return(FALSE);
  125. }
  126.  
  127.  
  128. /*---------------------------------------------------------------------------*\
  129. | BOUNCE COMMAND PROCEDURE
  130. |
  131. \*---------------------------------------------------------------------------*/
  132. BOOL BounceCommandProc(HWND hWnd, WPARAM wParam, LONG lParam)
  133. {
  134.     hWnd   = hWnd;
  135.     wParam = wParam;
  136.     lParam = lParam;
  137.  
  138.     return(TRUE);
  139. }
  140.  
  141.  
  142. /*---------------------------------------------------------------------------*\
  143. | BOUNCE PAINT PROCEDURE
  144. |
  145. \*---------------------------------------------------------------------------*/
  146. VOID BouncePaintProc(HWND hWnd)
  147. {
  148.     HDC         hDC;
  149.     PAINTSTRUCT ps;
  150.  
  151.  
  152.     if(hDC = BeginPaint(hWnd,&ps))
  153.         EndPaint(hWnd,&ps);
  154.  
  155.     BounceRefresh(hWnd);
  156.  
  157.     return;
  158. }
  159.  
  160.  
  161. /*---------------------------------------------------------------------------*\
  162. | BOUNCE DESTROY PROCEDURE
  163. |
  164. \*---------------------------------------------------------------------------*/
  165. VOID BounceDestroyProc(HWND hWnd)
  166. {
  167.     PBOUNCEDATA pbd;
  168.  
  169.  
  170.     KillTimer(hWnd,1);
  171.     if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
  172.     {
  173.         ballDestroy(pbd->hBall1);
  174.         ballDestroy(pbd->hBall2);
  175.         ballDestroy(pbd->hBall3);
  176.         ballDestroy(pbd->hBall4);
  177.  
  178.         UnlockWindowInfo(hWnd);
  179.     }
  180.     FreeWindowInfo(hWnd);
  181.     return;
  182. }
  183.  
  184.  
  185. /*---------------------------------------------------------------------------*\
  186. | BOUNCE REFRESH
  187. |
  188. \*---------------------------------------------------------------------------*/
  189. VOID BounceRefresh(HWND hWnd)
  190. {
  191.     PBOUNCEDATA pbd;
  192.     RECT        rect;
  193.     HDC         hDC;
  194.     POINT       pDimensions;
  195.     int         xDirection,yDirection;
  196.  
  197.  
  198.     if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
  199.     {
  200.         if(hDC = GetDC(hWnd))
  201.         {
  202.             GetClientRect(hWnd,&rect);
  203.             FillRect(hDC,&rect,GETCLASSBRUSH(hWnd));
  204.  
  205.             xDirection = ((lRandom() % 5)+5);
  206.             yDirection = ((lRandom() % 5)+5);
  207.             ballSetPosition(pbd->hBall1,0,0);
  208.             ballSetDirection(pbd->hBall1,xDirection,yDirection);
  209.  
  210.  
  211.             ballGetDimensions(pbd->hBall2,&pDimensions);
  212.             ballSetPosition(pbd->hBall2,rect.right-pDimensions.x,0);
  213.             xDirection = -(((int)lRandom() % 5)+5);
  214.             yDirection =  ((lRandom() % 5)+5);
  215.             ballSetDirection(pbd->hBall2,xDirection,yDirection);
  216.  
  217.  
  218.             ballGetDimensions(pbd->hBall3,&pDimensions);
  219.             ballSetPosition(pbd->hBall3,0,rect.bottom-pDimensions.y);
  220.             xDirection =  ((lRandom() % 5)+5);
  221.             yDirection = -((int)(lRandom() % 5)+5);
  222.             ballSetDirection(pbd->hBall3,xDirection,yDirection);
  223.  
  224.  
  225.             ballGetDimensions(pbd->hBall4,&pDimensions);
  226.             ballSetPosition(pbd->hBall4,rect.right-pDimensions.x,rect.bottom-pDimensions.y);
  227.             xDirection = -((int)(lRandom() % 5)+5);
  228.             yDirection = -((int)(lRandom() % 5)+5);
  229.             ballSetDirection(pbd->hBall4,xDirection,yDirection);
  230.  
  231.  
  232.             ballBounce(pbd->hBall1);
  233.             ballBounce(pbd->hBall2);
  234.             ballBounce(pbd->hBall3);
  235.             ballBounce(pbd->hBall4);
  236.  
  237.             ReleaseDC(hWnd,hDC);
  238.         }
  239.         UnlockWindowInfo(hWnd);
  240.     }
  241.     return;
  242. }
  243.  
  244.  
  245.  
  246. VOID BounceObjects(HWND hWnd)
  247. {
  248.     PBOUNCEDATA pbd;
  249.  
  250.  
  251.     if(pbd = (PBOUNCEDATA)LockWindowInfo(hWnd))
  252.     {
  253.         /*
  254.         ** Determine if the balls hit any of the edges of the display.  If
  255.         ** they do, then these functions reset their position to something
  256.         ** more desireable and re-do their direction.
  257.         */
  258.         CheckEdgePosition(hWnd,pbd->hBall1);
  259.         CheckEdgePosition(hWnd,pbd->hBall2);
  260.         CheckEdgePosition(hWnd,pbd->hBall3);
  261.         CheckEdgePosition(hWnd,pbd->hBall4);
  262.  
  263.         ballBounce(pbd->hBall1);
  264.         ballBounce(pbd->hBall2);
  265.         ballBounce(pbd->hBall3);
  266.         ballBounce(pbd->hBall4);
  267.  
  268.  
  269.         UnlockWindowInfo(hWnd);
  270.     }
  271.     return;
  272. }
  273.  
  274.  
  275. VOID CheckEdgePosition(HWND hWnd, HANDLE hBall)
  276. {
  277.     POINT pPos,pDir,pDim;
  278.     int   xNewPos,yNewPos,xNewDir,yNewDir;
  279.     RECT  rect;
  280.  
  281.  
  282.  
  283.     ballGetPosition(hBall,&pPos);
  284.     ballGetDirection(hBall,&pDir);
  285.     ballGetDimensions(hBall,&pDim);
  286.  
  287.     GetClientRect(hWnd,&rect);
  288.  
  289.  
  290.     /*
  291.     ** Check each edge of the client rectagle.  If the ball goes past the
  292.     ** boundries, reset the position and give it a new direction.
  293.     */
  294.     xNewDir = pDir.x;
  295.     yNewDir = pDir.y;
  296.     xNewPos = pPos.x+pDir.x;
  297.     yNewPos = pPos.y+pDir.y;
  298.  
  299.     if(xNewPos < rect.left)
  300.     {
  301.         xNewDir = ((lRandom() % 5)+5);
  302.         ballSetPosition(hBall,rect.left,pPos.y);
  303.     }
  304.     if((xNewPos+pDim.x) > rect.right)
  305.     {
  306.         xNewDir = -(((int)lRandom() % 5)+5);
  307.         ballSetPosition(hBall,rect.right-pDim.x,pPos.y);
  308.     }
  309.     if(yNewPos < rect.top)
  310.     {
  311.         yNewDir = ((lRandom() % 5)+5);
  312.         ballSetPosition(hBall,pPos.x,rect.top);
  313.     }
  314.     if((yNewPos+pDim.y) > rect.bottom)
  315.     {
  316.         yNewDir = -(((int)lRandom() % 5)+5);
  317.         ballSetPosition(hBall,pPos.x,rect.bottom-pDim.y);
  318.     }
  319.     ballSetDirection(hBall,xNewDir,yNewDir);
  320.  
  321.     return;
  322. }
  323.  
  324.  
  325. /*---------------------------------------------------------------------------*\
  326. | CLEAR XFORM
  327. |
  328. \*---------------------------------------------------------------------------*/
  329. VOID XFormClear(PMYXFORM pXForm)
  330. {
  331.     int Row,Col;
  332.  
  333.  
  334.     for(Row=0; Row < 3; Row++)
  335.         for(Col=0; Col < 3; Col++)
  336.             if(Row == Col)
  337.                 pXForm->xForm[Row][Col] = 1;
  338.             else
  339.                 pXForm->xForm[Row][Col] = 0;
  340.     return;
  341. }
  342.  
  343.  
  344. /*---------------------------------------------------------------------------*\
  345. | XFORM SCALE
  346. |
  347. \*---------------------------------------------------------------------------*/
  348. VOID XFormScale(PMYXFORM pXForm, int xScale, int yScale)
  349. {
  350.     int idx;
  351.  
  352.  
  353.     for(idx=0; idx < 3; idx++)
  354.     {
  355.         pXForm->xForm[idx][0] = pXForm->xForm[idx][0] * xScale;
  356.         pXForm->xForm[idx][1] = pXForm->xForm[idx][1] * yScale;
  357.     }
  358.     return;
  359. }
  360.  
  361.  
  362.  
  363. VOID XFormTrans(PMYXFORM pXForm, int xTrans, int yTrans)
  364. {
  365.     pXForm->xForm[2][0] = pXForm->xForm[2][0] + xTrans;
  366.     pXForm->xForm[2][1] = pXForm->xForm[2][1] + yTrans;
  367.  
  368.     return;
  369. }
  370.  
  371.  
  372.  
  373. VOID XFormPoint(PMYXFORM pXForm, LPPOINT pPoint)
  374. {
  375.     int x,y;
  376.  
  377.  
  378.     x = (pXForm->xForm[0][0] * pPoint->x) + (pXForm->xForm[1][0] * pPoint->y) + pXForm->xForm[2][0];
  379.     y = (pXForm->xForm[0][1] * pPoint->x) + (pXForm->xForm[1][1] * pPoint->y) + pXForm->xForm[2][1];
  380.  
  381.     pPoint->x = x;
  382.     pPoint->y = y;
  383.  
  384.     return;
  385. }
  386.  
  387.  
  388. /*
  389. ** -------------------------------
  390. ** -------------------------------
  391. ** -------------------------------
  392. */
  393.  
  394. HANDLE ballCreate(HWND hWnd, int nWidth, int nHeight, COLORREF crColor)
  395. {
  396.     HANDLE    hBall;
  397.     PBALLDATA pbd;
  398.  
  399.     if(hBall = LocalAlloc(LHND,sizeof(BALLDATA)))
  400.     {
  401.         if(pbd = (PBALLDATA)LocalLock(hBall))
  402.         {
  403.             pbd->hWnd         = hWnd;
  404.             pbd->nWidth       = nWidth;
  405.             pbd->nHeight      = nHeight;
  406.             pbd->xDirection   = 0;
  407.             pbd->yDirection   = 0;
  408.             pbd->bNewPosition = FALSE;
  409.             pbd->xPosition    = 0;
  410.             pbd->yPosition    = 0;
  411.             pbd->crColor      = crColor;
  412.             XFormClear(&pbd->xForm);
  413.  
  414.             LocalUnlock(hBall);
  415.             return(hBall);
  416.         }
  417.         LocalFree(hBall);
  418.     }
  419.     return(NULL);
  420. }
  421.  
  422.  
  423. BOOL ballDestroy(HANDLE hBall)
  424. {
  425.     if(LocalFree(hBall))
  426.         return(FALSE);
  427.     return(TRUE);
  428. }
  429.  
  430.  
  431. VOID ballBounce(HANDLE hBall)
  432. {
  433.     PBALLDATA pbd;
  434.     HDC       hDC;
  435.     HBRUSH    hBrush;
  436.     POINT     pOrg,pExt;
  437.     HRGN      hTmp,hOld,hNew;
  438.  
  439.  
  440.     if(pbd = (PBALLDATA)LocalLock(hBall))
  441.     {
  442.         /*
  443.         ** Create old ball object.
  444.         */
  445.         pOrg.x = 0;
  446.         pOrg.y = 0;
  447.         pExt.x = pbd->nWidth;
  448.         pExt.y = pbd->nHeight;
  449.         XFormPoint(&pbd->xForm,&pOrg);
  450.         XFormPoint(&pbd->xForm,&pExt);
  451.         hOld = CreateEllipticRgn(pOrg.x,pOrg.y,pExt.x,pExt.y);
  452.  
  453.  
  454.         /*
  455.         ** Create new ball object.
  456.         */
  457.         if(pbd->bNewPosition)
  458.         {
  459.             pbd->bNewPosition = FALSE;
  460.             XFormClear(&pbd->xForm);
  461.             XFormTrans(&pbd->xForm,pbd->xPosition,pbd->yPosition);
  462.         }
  463.         else
  464.             XFormTrans(&pbd->xForm,pbd->xDirection,pbd->yDirection);
  465.         pOrg.x = 0;
  466.         pOrg.y = 0;
  467.         pExt.x = pbd->nWidth;
  468.         pExt.y = pbd->nHeight;
  469.         XFormPoint(&pbd->xForm,&pOrg);
  470.         XFormPoint(&pbd->xForm,&pExt);
  471.         hNew = CreateEllipticRgn(pOrg.x,pOrg.y,pExt.x,pExt.y);
  472.  
  473.  
  474.  
  475.         if(hDC = GetDC(pbd->hWnd))
  476.         {
  477.             hTmp = CreateRectRgn(1,1,2,2);
  478.             CombineRgn(hTmp,hOld,hNew,RGN_DIFF);
  479.             FillRgn(hDC,hTmp,GETCLASSBRUSH(pbd->hWnd));
  480.  
  481.             hBrush = CreateSolidBrush(pbd->crColor);
  482.             FillRgn(hDC,hNew,hBrush);
  483.             DeleteObject(hBrush);
  484.  
  485.             ReleaseDC(pbd->hWnd,hDC);
  486.  
  487.             DeleteObject(hTmp);
  488.         }
  489.  
  490.         DeleteObject(hOld);
  491.         DeleteObject(hNew);
  492.  
  493.         LocalUnlock(hBall);
  494.     }
  495.     return;
  496. }
  497.  
  498.  
  499. BOOL ballGetDimensions(HANDLE hBall, LPPOINT pDimension)
  500. {
  501.     PBALLDATA pbd;
  502.     BOOL      bOK;
  503.  
  504.  
  505.     bOK = FALSE;
  506.     if(pbd = (PBALLDATA)LocalLock(hBall))
  507.     {
  508.         pDimension->x = pbd->nWidth;
  509.         pDimension->y = pbd->nHeight;
  510.  
  511.         bOK = TRUE;
  512.         LocalUnlock(hBall);
  513.     }
  514.     return(bOK);
  515. }
  516.  
  517.  
  518. BOOL ballSetDimensions(HANDLE hBall, int nWidth, int nHeight)
  519. {
  520.     PBALLDATA pbd;
  521.     BOOL      bOK;
  522.  
  523.  
  524.     bOK = FALSE;
  525.     if(pbd = (PBALLDATA)LocalLock(hBall))
  526.     {
  527.         pbd->nWidth  = nWidth;
  528.         pbd->nHeight = nHeight;
  529.  
  530.         bOK = TRUE;
  531.         LocalUnlock(hBall);
  532.     }
  533.     return(bOK);
  534. }
  535.  
  536.  
  537. BOOL ballGetDirection(HANDLE hBall, LPPOINT pDirection)
  538. {
  539.     PBALLDATA pbd;
  540.     BOOL      bOK;
  541.  
  542.  
  543.     bOK = FALSE;
  544.     if(pbd = (PBALLDATA)LocalLock(hBall))
  545.     {
  546.         pDirection->x = pbd->xDirection;
  547.         pDirection->y = pbd->yDirection;
  548.  
  549.         bOK = TRUE;
  550.         LocalUnlock(hBall);
  551.     }
  552.     return(bOK);
  553. }
  554.  
  555.  
  556. BOOL ballSetDirection(HANDLE hBall, int xDirection, int yDirection)
  557. {
  558.     PBALLDATA pbd;
  559.     BOOL      bOK;
  560.  
  561.  
  562.     bOK = FALSE;
  563.     if(pbd = (PBALLDATA)LocalLock(hBall))
  564.     {
  565.         pbd->xDirection = xDirection;
  566.         pbd->yDirection = yDirection;
  567.  
  568.         bOK = TRUE;
  569.         LocalUnlock(hBall);
  570.     }
  571.     return(bOK);
  572. }
  573.  
  574.  
  575. BOOL ballGetPosition(HANDLE hBall, LPPOINT pPosition)
  576. {
  577.     PBALLDATA pbd;
  578.     BOOL      bOK;
  579.     POINT     pOrg;
  580.  
  581.  
  582.     bOK = FALSE;
  583.     if(pbd = (PBALLDATA)LocalLock(hBall))
  584.     {
  585.         pOrg.x = 0;
  586.         pOrg.y = 0;
  587.         XFormPoint(&pbd->xForm,&pOrg);
  588.  
  589.         pPosition->x = pOrg.x;
  590.         pPosition->y = pOrg.y;
  591.  
  592.         bOK = TRUE;
  593.         LocalUnlock(hBall);
  594.     }
  595.     return(bOK);
  596. }
  597.  
  598.  
  599. BOOL ballSetPosition(HANDLE hBall, int x, int y)
  600. {
  601.     PBALLDATA pbd;
  602.     BOOL      bOK;
  603.  
  604.  
  605.     bOK = FALSE;
  606.     if(pbd = (PBALLDATA)LocalLock(hBall))
  607.     {
  608.         pbd->bNewPosition = TRUE;
  609.         pbd->xPosition    = x;
  610.         pbd->yPosition    = y;
  611.  
  612.         bOK = TRUE;
  613.         LocalUnlock(hBall);
  614.     }
  615.     return(bOK);
  616. }
  617.