home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible / OpenGL_Superbible_Waite_Group_Press_1996.iso / book / chapt10 / tank / borland / tank.c < prev    next >
C/C++ Source or Header  |  1996-07-07  |  13KB  |  502 lines

  1. // Tank.c
  2. // This is the application shell for the tank simulator
  3.  
  4. // Include files
  5. #include <windows.h>            // Window defines
  6. #include <math.h>                // Include for sqrt()
  7. #include <gl\gl.h>              // OpenGL
  8. #include <gl\glu.h>             // GLU library
  9. #include "resource.h"           // About box and other resource identifiers.
  10. #include "glutils.h"            // OpenGL support functions
  11.  
  12.  
  13. ///////////////////////////////////////////////////////////////////////////
  14. // Declaration of shared handles, etc. These are declared as externs in the
  15. // header file externs.h
  16. HWND     hRadarWnd = NULL;
  17. HWND     hCenterWnd = NULL;
  18. HWND     hCompassWnd= NULL;
  19. HWND     hViewWnd = NULL;
  20. HWND     hMainWnd = NULL;
  21.  
  22. HPALETTE hPalette = NULL;
  23.  
  24. // Tank and robot position
  25. struct _POSITION tankPos;    // Tanks position
  26. struct _POSITION robotPos;    // Robots position
  27. struct _POSITION *pObject;    // Which one is current
  28.  
  29.  
  30. // Real simple, if this is true, your the tank, if false, your the robot
  31. BOOL bTank = TRUE;
  32. BOOL bDrawShadows = FALSE;
  33.  
  34. // Display list identifiers
  35. int nWorldList = 10000;
  36. int nCompassList = 10001;
  37.  
  38. // This is going to come in handy more than once.
  39. double     PI =  3.14159265359;
  40.  
  41. // Class Names for all the window classes in this application
  42. static LPCTSTR lpszMainWndClass = "MainClass";
  43. static LPCTSTR lpszCenterWndClass = "CenterClass";
  44. static LPCTSTR lpszCompassWndClass = "CompassClass";
  45. static LPCTSTR lpszRadarWndClass = "RadarClass";
  46. static LPCTSTR lpszViewWndClass = "ViewClass";
  47.  
  48.  
  49. // Application name and instance storeage
  50. static LPCTSTR lpszAppName = "GL Tank";
  51. static HINSTANCE hInstance;
  52.  
  53.  
  54. // Declaration for Window procedures
  55. // Defined in this file (tank.c)
  56. LRESULT CALLBACK WndProcMain(HWND    hWnd,
  57.                             UINT    message,
  58.                             WPARAM  wParam,
  59.                             LPARAM  lParam);
  60.  
  61. // Declaration for Window procedures
  62. // See CompassWnd.c
  63. LRESULT CALLBACK WndProcCompass(HWND    hWnd,
  64.                             UINT    message,
  65.                             WPARAM  wParam,
  66.                             LPARAM  lParam);
  67.  
  68. // Declaration for Window procedures
  69. // See CenterWnd.c
  70. LRESULT CALLBACK WndProcCenter(HWND    hWnd,
  71.                             UINT    message,
  72.                             WPARAM  wParam,
  73.                             LPARAM  lParam);
  74.  
  75. // Declaration for Window procedures
  76. // See RadarWnd.c
  77. LRESULT CALLBACK WndProcRadar(HWND    hWnd,
  78.                             UINT    message,
  79.                             WPARAM  wParam,
  80.                             LPARAM  lParam);
  81.  
  82. // Declaration for Window procedure
  83. // See ViewWnd.c
  84. LRESULT CALLBACK WndProcView(HWND    hWnd,
  85.                             UINT    message,
  86.                             WPARAM  wParam,
  87.                             LPARAM  lParam);
  88.  
  89.  
  90. // Dialog procedure for about box
  91. BOOL APIENTRY AboutDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam);
  92. BOOL BuildClasses(void);
  93.  
  94.  
  95. ///////////////////////////////////////////////////////////////////////////////
  96. // Create the window classes. Returns FALSE if any errors occur
  97. BOOL BuildClasses(void)
  98.     {
  99.     WNDCLASS        wc;                // Windows class structure
  100.  
  101.     // Register window style for the main window
  102.     wc.style                = CS_HREDRAW | CS_VREDRAW;
  103.     wc.lpfnWndProc          = (WNDPROC) WndProcMain;
  104.     wc.cbClsExtra           = 0;
  105.     wc.cbWndExtra           = 0;
  106.     wc.hInstance            = hInstance;
  107.     wc.hIcon                = NULL;
  108.     wc.hCursor              = LoadCursor(NULL, IDC_ARROW);
  109.     
  110.     // No need for background brush for this window
  111.     wc.hbrBackground        = NULL;          
  112.     
  113.     wc.lpszMenuName         = MAKEINTRESOURCE(IDR_MENU);
  114.     wc.lpszClassName        = lpszMainWndClass;
  115.  
  116.     // Register the window class
  117.     if(RegisterClass(&wc) == 0)
  118.         return FALSE;
  119.  
  120.  
  121.     // Register window style for the center window
  122.     // Most info is the same
  123.     wc.lpfnWndProc          = (WNDPROC) WndProcCenter;
  124.     
  125.     // May want to change later
  126.     wc.hbrBackground        = GetStockObject(WHITE_BRUSH);         
  127.     wc.lpszClassName        = lpszCenterWndClass;
  128.  
  129.     // Register the window class
  130.     if(RegisterClass(&wc) == 0)
  131.         return FALSE;
  132.  
  133.  
  134.     // Register window style for the control window
  135.     wc.lpfnWndProc          = (WNDPROC) WndProcRadar;
  136.  
  137.     wc.hbrBackground        = GetStockObject(BLACK_BRUSH);         
  138.     wc.lpszClassName        = lpszRadarWndClass;
  139.  
  140.     // Register the window class
  141.     if(RegisterClass(&wc) == 0)
  142.         return FALSE;
  143.  
  144.  
  145.     // Register window style for the main view window
  146.     // This is a window OpenGL will render in
  147.     wc.style                = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  148.     wc.lpfnWndProc          = (WNDPROC) WndProcView;
  149.  
  150.     // May want to change the cursor
  151.     wc.hCursor              = LoadCursor(NULL, IDC_ARROW);
  152.     
  153.     // No need for background brush for this window
  154.     // Delete me later
  155.     wc.hbrBackground        = NULL;
  156.     wc.lpszClassName        = lpszViewWndClass;
  157.  
  158.     // Register the window class
  159.     if(RegisterClass(&wc) == 0)
  160.         return FALSE;
  161.  
  162.     // Register window style for the Map window, OpenGL will also render
  163.     // into this window.
  164.     // Most Info is the same
  165.     wc.lpfnWndProc          = (WNDPROC) WndProcCompass;
  166.     wc.lpszClassName        = lpszCompassWndClass;
  167.  
  168.     // Register the window class
  169.     if(RegisterClass(&wc) == 0)
  170.         return FALSE;
  171.  
  172.  
  173.     return TRUE;
  174.     }
  175.  
  176.  
  177. ///////////////////////////////////////////////////////////////////////////////
  178. // Entry point of all Windows programs
  179. int APIENTRY WinMain(   HINSTANCE       hInst,
  180.                         HINSTANCE       hPrevInstance,
  181.                         LPSTR           lpCmdLine,
  182.                         int             nCmdShow)
  183.     {
  184.     MSG             msg;            // Windows message structure
  185.  
  186.     // Variable is scoped to this file
  187.     hInstance = hInst;
  188.  
  189.  
  190.     // Create the window classes for the main window and the
  191.     // children
  192.     if(!BuildClasses())
  193.         return FALSE;
  194.  
  195.     // Initializes the world geography
  196.     if(!InitWorld())
  197.         return FALSE;
  198.  
  199.     // Create the main application window
  200.     hMainWnd = CreateWindow(
  201.                     lpszMainWndClass,
  202.                     lpszAppName,
  203.                     WS_CAPTION | WS_BORDER | WS_SYSMENU,
  204.                     0, 0,               // Size and dimensions of window
  205.                     640, 480,
  206.                     NULL,
  207.                     NULL,
  208.                     hInstance,
  209.                     NULL);
  210.  
  211.     // Display the window
  212.     ShowWindow(hMainWnd,SW_SHOW);
  213.     UpdateWindow(hMainWnd);
  214.  
  215.     // Process application messages until the application closes
  216.     while( GetMessage(&msg, NULL, 0, 0))
  217.         {
  218.         TranslateMessage(&msg);
  219.         DispatchMessage(&msg);
  220.         }
  221.  
  222.     return msg.wParam;
  223.     }
  224.  
  225.  
  226.  
  227. ///////////////////////////////////////////////////////////////////////////////
  228. // Window procedure, handles all top messages for this program
  229. LRESULT CALLBACK WndProcMain(HWND    hWnd,
  230.                             UINT    message,
  231.                             WPARAM  wParam,
  232.                             LPARAM  lParam)
  233.     {
  234.     switch (message)
  235.         {
  236.         // Window creation, setup here
  237.         case WM_CREATE:
  238.             {
  239.             HANDLE hMenu = GetMenu(hWnd);
  240.  
  241.             // Set initial menu check state
  242.             CheckMenuItem(hMenu,ID_VIEW_FROMTANK,MF_BYCOMMAND | MF_CHECKED);
  243.             
  244.             
  245.             // Create the child windows
  246.             // View Window
  247.             hViewWnd = CreateWindow(
  248.                     lpszViewWndClass,
  249.                     NULL,
  250.                     WS_DLGFRAME | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS| WS_VISIBLE,
  251.                     0, 0,               
  252.                     10, 10,
  253.                     hWnd,
  254.                     NULL,
  255.                     hInstance,
  256.                     NULL);
  257.  
  258.             // Compass Window
  259.             hCompassWnd = CreateWindow(
  260.                     lpszCompassWndClass,
  261.                     NULL,
  262.                     WS_DLGFRAME | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS| WS_VISIBLE,
  263.                     1, 1,               
  264.                     10, 10,
  265.                     hWnd,
  266.                     NULL,
  267.                     hInstance,
  268.                     NULL);
  269.  
  270.             // Center Window, just contains the instructions
  271.             hCenterWnd = CreateWindow(
  272.                     lpszCenterWndClass,
  273.                     NULL,
  274.                     WS_DLGFRAME | WS_CHILD | WS_VISIBLE,
  275.                     1, 1,               
  276.                     10, 10,
  277.                     hWnd,
  278.                     NULL,
  279.                     hInstance,
  280.                     NULL);
  281.  
  282.             // Radar Window
  283.             hRadarWnd = CreateWindow(
  284.                     lpszRadarWndClass,
  285.                     NULL,
  286.                     WS_DLGFRAME | WS_CHILD | WS_VISIBLE,
  287.                     1, 1,               
  288.                     10, 10,
  289.                     hWnd,
  290.                     NULL,
  291.                     hInstance,
  292.                     NULL);
  293.             }
  294.             break;
  295.  
  296.         // Window is being destroyed, cleanup
  297.         case WM_DESTROY:
  298.  
  299.             // Tell the application to terminate after the window
  300.             // is gone.
  301.             PostQuitMessage(0);
  302.             break;
  303.  
  304.         // Window is resized.
  305.         // This is really only going to be called once. Why resize here
  306.         // instead of just creating the windows where we want them? Because
  307.         // changes to the GUI may change the size of borders, etc. This
  308.         // code should continue to work regardless of any changes to the
  309.         // GUI. 
  310.         case WM_SIZE:
  311.             {
  312.             RECT clientRect;
  313.             int width,height;
  314.  
  315.             GetClientRect(hMainWnd,&clientRect);
  316.  
  317.             // Position the viewing window
  318.             width = clientRect.right - clientRect.left;
  319.             height = (clientRect.bottom*2)/5;
  320.             MoveWindow(hViewWnd,0,height,
  321.                     width,clientRect.bottom-height,TRUE);
  322.  
  323.             // Position the Map Window
  324.             MoveWindow(hCompassWnd,0,0,175,height,TRUE);
  325.  
  326.             // Position the Center Window
  327.             MoveWindow(hCenterWnd,175,0,
  328.                     clientRect.right-350,height,TRUE);
  329.  
  330.             // Position the Control Window
  331.             MoveWindow(hRadarWnd,width-175,0,
  332.                             175,height,TRUE);
  333.             }
  334.             break;
  335.  
  336.         // Windows is telling the application that it may modify
  337.         // the system palette.  This message in essance asks the 
  338.         // application for a new palette.
  339.         case WM_QUERYNEWPALETTE:
  340.             // Pass the message to the OpenGL Windows, none of the other
  341.             // Windows use anything outside the standard set of colors
  342.             PostMessage(hViewWnd,message,wParam,lParam);
  343.             PostMessage(hRadarWnd,message,wParam,lParam);
  344.             break;
  345.  
  346.     
  347.         // This window may set the palette, even though it is not the 
  348.         // currently active window.
  349.         case WM_PALETTECHANGED:
  350.             // Pass the message to the OpenGL Windows, none of the other
  351.             // Windows use anything outside the standard 16 colors
  352.             PostMessage(hViewWnd,message,wParam,lParam);
  353.             PostMessage(hRadarWnd,message,wParam,lParam);
  354.             break;
  355.  
  356.         // Catch and handle the arrow keys for movement
  357.         case WM_KEYDOWN:
  358.             {
  359.             switch(wParam)
  360.                 {
  361.                 case VK_UP:        // Up arrow, move forward
  362.                     {
  363.                     MoveViewer(10.0);                    
  364.  
  365.                     // Invalidate the view window (compass doesn't change)
  366.                     InvalidateRect(hViewWnd,NULL,FALSE);
  367.                     break;
  368.                     }
  369.  
  370.                 case VK_DOWN: // Down arrow, move backward
  371.                     {
  372.                     MoveViewer(-10.0);
  373.  
  374.                     // Invalidate the view window (compass doesn't change)
  375.                     InvalidateRect(hViewWnd,NULL,FALSE);
  376.                     break;
  377.                     }
  378.  
  379.                 case VK_LEFT:        // Left arrow, turn left
  380.                     {
  381.                     pObject->radsFromEast += PI/30.0f; 
  382.  
  383.                     if(pObject->radsFromEast > (2.0*PI))        // Keep in bounds
  384.                         pObject->radsFromEast = 0.0;
  385.             
  386.                     // Invalidate the compass window and view window
  387.                     InvalidateRect(hCompassWnd,NULL,FALSE);
  388.                     InvalidateRect(hViewWnd,NULL,FALSE);
  389.                     break;
  390.                     }
  391.         
  392.                 case VK_RIGHT:        // Right Arrow, turn right
  393.                     {
  394.                     pObject->radsFromEast -= PI/30.0; 
  395.                 
  396.                     if(pObject->radsFromEast < 0.0)
  397.                         pObject->radsFromEast = (2.0*PI);    // Keep in bounds
  398.                     
  399.                     // Invalidate the compass window and view window
  400.                     InvalidateRect(hCompassWnd,NULL,FALSE);
  401.                     InvalidateRect(hViewWnd,NULL,FALSE);
  402.                     break;
  403.                     }
  404.                 }
  405.             }
  406.             break;
  407.             
  408.     
  409.         // A menu command
  410.         case WM_COMMAND:
  411.             {
  412.             HANDLE hMenu = GetMenu(hWnd);
  413.  
  414.             switch(LOWORD(wParam))
  415.                 {
  416.                 // Exit the program
  417.                 case ID_FILE_EXIT:
  418.                     DestroyWindow(hWnd);
  419.                     break;
  420.  
  421.                 // Display the about box
  422.                 case ID_HELP_ABOUT:
  423.                     DialogBox (hInstance,
  424.                         MAKEINTRESOURCE(IDD_DIALOG_ABOUT),
  425.                         hWnd,
  426.                         AboutDlgProc);
  427.                     break;
  428.  
  429.                 // View is from tank
  430.                 case ID_VIEW_FROMTANK:
  431.                     bTank = TRUE;
  432.                     pObject = &tankPos;
  433.  
  434.                     CheckMenuItem(hMenu,ID_VIEW_FROMTANK,MF_BYCOMMAND | MF_CHECKED);
  435.                     CheckMenuItem(hMenu,ID_VIEW_FROMROBOT,MF_BYCOMMAND | MF_UNCHECKED);
  436.  
  437.                     // Invalidate the compass window and view window
  438.                     InvalidateRect(hCompassWnd,NULL,FALSE);
  439.                     InvalidateRect(hViewWnd,NULL,FALSE);
  440.                     break;
  441.  
  442.  
  443.                 // View is from robot
  444.                 case ID_VIEW_FROMROBOT:
  445.                     bTank = FALSE;
  446.                     pObject = &robotPos;
  447.  
  448.                     CheckMenuItem(hMenu,ID_VIEW_FROMTANK,MF_BYCOMMAND | MF_UNCHECKED);
  449.                     CheckMenuItem(hMenu,ID_VIEW_FROMROBOT,MF_BYCOMMAND | MF_CHECKED);
  450.  
  451.                     // Invalidate the compass window and view window
  452.                     InvalidateRect(hCompassWnd,NULL,FALSE);
  453.                     InvalidateRect(hViewWnd,NULL,FALSE);
  454.                     break;
  455.  
  456.                 }
  457.             }
  458.             break;
  459.  
  460.  
  461.     default:   // Passes it on if unproccessed
  462.         return (DefWindowProc(hWnd, message, wParam, lParam));
  463.  
  464.     }
  465.  
  466.     return (0L);
  467.     }
  468.  
  469.  
  470.  
  471. ///////////////////////////////////////////////////////////////////////////
  472. // Dialog procedure 
  473. BOOL APIENTRY AboutDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam)
  474.     {
  475.     switch (message)
  476.         {
  477.         // Process command messages
  478.         case WM_COMMAND:      
  479.             {
  480.             // Validate and Make the changes
  481.             if(LOWORD(wParam) == IDOK)
  482.                 EndDialog(hDlg,TRUE);
  483.             }
  484.             break;
  485.  
  486.         // Closed from sysbox
  487.         case WM_CLOSE:
  488.             EndDialog(hDlg,TRUE);
  489.             break;
  490.         }
  491.  
  492.     return FALSE;
  493.     }
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.