donuts.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:98k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: Donuts.cpp
  3. //
  4. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  5. //-----------------------------------------------------------------------------
  6. #include "stdafx.h"
  7. //-----------------------------------------------------------------------------
  8. // Globals
  9. //-----------------------------------------------------------------------------
  10. // This GUID must be unique for every game, and the same for 
  11. // every instance of this app.  // {769FCCA3-150E-4514-A9E2-E28449A7C401}
  12. // The GUID allows DirectInput to remember input settings
  13. GUID g_guidApp = { 0x769fcca3, 0x150e, 0x4514, { 0xa9, 0xe2, 0xe2, 0x84, 0x49, 0xa7, 0xc4, 0x01 } };
  14. CMyApplication*    g_pApp       = NULL;             // Global access to the app 
  15. HINSTANCE          g_hInst      = NULL;             // Global HINSTANCE
  16. CProfile           g_Profile;                       // Read & stores settings for the game from .ini
  17. CTerrainEngine*    g_pTerrain   = NULL;             // Terrian engine owns the graphics objects
  18. IDirect3DDevice9*  g_pd3dDevice = NULL;             // Class to handle D3D device
  19. C3DDrawManager*    g_p3DDrawManager = NULL;         // for debugging
  20. //-----------------------------------------------------------------------------
  21. // Name: WinMain()
  22. // Desc: Application entry point
  23. //-----------------------------------------------------------------------------
  24. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
  25. {
  26.     CMyApplication app;
  27.     srand( timeGetTime() );
  28.     g_hInst = hInstance;
  29.     if( FAILED( app.Create( hInstance ) ) )
  30.         return 0;
  31.     return app.Run();
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Name: CMyApplication()
  35. // Desc: Constructor
  36. //-----------------------------------------------------------------------------
  37. CMyApplication::CMyApplication()
  38. {
  39.     g_pApp                  = this;
  40.     m_fTime                 = 0.0f;
  41.     m_strAppName            = _T("Donuts 4: Revenge of the Space Torus");
  42.     m_hWndMain              = NULL;               
  43.     m_dwScreenWidth         = 1024;   
  44.     m_dwScreenHeight        = 768;
  45.     m_bFullScreen           = FALSE; 
  46.     m_bIsActive             = FALSE; 
  47.     m_bDisplayReady         = FALSE; 
  48.     m_bMouseVisible         = FALSE;  
  49.     m_dwAppState            = APPSTATE_LOADSPLASH;              
  50.     m_dwLevel               = 0;     
  51.     m_fFPS                  = 0.0f;
  52.     m_pInputManager         = NULL;
  53.     m_pShip                 = NULL;          
  54.     m_pViewportVB           = NULL;
  55.     m_pRadarVB              = NULL;
  56.     m_pSkyDome              = NULL; 
  57.     m_pFileWatch            = NULL;
  58.     m_p3DListener           = NULL;
  59.     m_pBullet1Sound         = NULL;
  60.     m_pExplosionDonutSound  = NULL;
  61.     m_pMusicManager         = NULL;
  62.     m_pMusicScript          = NULL;
  63.     m_pEnginePath           = NULL;
  64.     m_pMusicManager         = NULL;  
  65.     m_pSkyTexture           = NULL; 
  66.     m_pRadarTexture         = NULL;
  67.     m_pTempRadarTexture     = NULL;
  68.     m_pUITexture            = NULL; 
  69.     g_pTerrain              = NULL;
  70.     m_pGameFont             = NULL;
  71.     m_pMenuFont             = NULL;
  72.     m_pMainMenu             = NULL;    
  73.     m_pQuitMenu             = NULL;
  74.     m_pCurrentMenu          = NULL;
  75.     m_p3DDrawManager        = NULL;
  76.     m_pSplashTexture        = NULL;
  77.     m_bPaused               = FALSE;
  78.     m_lSpeed                = 0;
  79.     m_bDebugMode            = FALSE;
  80.     m_bWireMode             = FALSE;
  81.     m_fRadarTextureX        = 0.0f;
  82.     m_fRadarTextureY        = 0.0f;
  83.     m_fPhysicsSimCaryyOver  = 0.0f;
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Name: Create()
  87. // Desc: Creates the window
  88. //-----------------------------------------------------------------------------
  89. HRESULT CMyApplication::Create( HINSTANCE hInstance )
  90. {
  91.     // Register the window class
  92.     WNDCLASS wndClass = { CS_DBLCLKS, StaticMsgProc, 0, 0, hInstance,
  93.                           LoadIcon( hInstance, MAKEINTRESOURCE(DONUTS_ICON) ),
  94.                           LoadCursor( NULL, IDC_ARROW ),
  95.                           (HBRUSH)GetStockObject( BLACK_BRUSH ),
  96.                           NULL, TEXT("Donuts4Class") };
  97.     RegisterClass( &wndClass );
  98.     
  99.     // Create our main window
  100.     m_hWndMain = CreateWindowEx( 0, TEXT("Donuts4Class"), m_strAppName,
  101.                                  WS_POPUP|WS_CAPTION|WS_SYSMENU,
  102.                                  0, 0, 640, 480, NULL, NULL,
  103.                                  hInstance, NULL );
  104.     if( NULL == m_hWndMain )
  105.         return E_FAIL;
  106.     UpdateWindow( m_hWndMain );
  107.     SetCursor( NULL );
  108.     SetFocus( m_hWndMain );
  109.     SetForegroundWindow( m_hWndMain );
  110.     // Save window properties
  111.     m_dwWindowStyle = GetWindowLong( m_hWndMain, GWL_STYLE );
  112.     GetWindowRect( m_hWndMain, &m_rcWindowBounds );
  113.     GetClientRect( m_hWndMain, &m_rcWindowClient );
  114.     // Create the game objects (display objects, sounds, input devices,
  115.     // menus, etc.)
  116.     if( FAILED( OneTimeSceneInit( m_hWndMain ) ) )
  117.     {
  118.         DestroyWindow( m_hWndMain );
  119.         return E_FAIL;
  120.     }
  121.     return S_OK;
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Name: Run()
  125. // Desc: Handles the message loop and calls UpdateScene() and Render() when
  126. //       idle.
  127. //-----------------------------------------------------------------------------
  128. INT CMyApplication::Run()
  129. {
  130.     // Now we're ready to recieve and process Windows messages.
  131.     BOOL bGotMsg;
  132.     MSG  msg;
  133.     PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
  134.     while( WM_QUIT != msg.message  )
  135.     {
  136.         // Use PeekMessage() if the app is active, so we can use idle time to
  137.         // render the scene. Else, use GetMessage() to avoid eating CPU time.
  138.         if( m_bIsActive )
  139.             bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
  140.         else
  141.             bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
  142.         if( bGotMsg )
  143.         {
  144.             // Translate and dispatch the message
  145.             TranslateMessage( &msg );
  146.             DispatchMessage( &msg );
  147.         }
  148.         else
  149.         {
  150.             // Render a frame during idle time (no messages are waiting)
  151.             if( m_bDisplayReady )
  152.             {
  153.                 if( m_pFileWatch->HaveFilesChanged( TRUE ) )
  154.                 {
  155.                     g_Profile.GetProfile( m_strProfilePath );
  156.                 }
  157.                 else
  158.                 {
  159.                     UpdateScene();
  160.                     RenderScene();
  161.                 }
  162.             }
  163.         }
  164.     }
  165.     return (int)msg.wParam;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Name: StaticMsgProc()
  169. // Desc: Static msg handler which passes messages to the application class.
  170. //-----------------------------------------------------------------------------
  171. LRESULT CALLBACK StaticMsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  172. {
  173.     return g_pApp->MsgProc( hWnd, uMsg, wParam, lParam );
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Name: MsgProc()
  177. // Desc: Callback for all Windows messages
  178. //-----------------------------------------------------------------------------
  179. LRESULT CMyApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  180. {
  181.     switch( msg )
  182.     {
  183.         case WM_ACTIVATEAPP:
  184.             m_bIsActive = (BOOL)wParam;
  185.             if( m_bIsActive )
  186.                 DXUtil_Timer( TIMER_START );
  187.             else
  188.                 DXUtil_Timer( TIMER_STOP );
  189.             break;
  190.         case WM_GETMINMAXINFO:
  191.             ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 320;
  192.             ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
  193.             break;
  194.         case WM_SETCURSOR:
  195.             if( !m_bMouseVisible )
  196.                 SetCursor( NULL );
  197.             else
  198.                 SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  199.             return TRUE;
  200.         case WM_SYSCOMMAND:
  201.             // Prevent moving/sizing and power loss
  202.             switch( wParam )
  203.             {
  204.                 case SC_MOVE:
  205.                 case SC_SIZE:
  206.                 case SC_MAXIMIZE:
  207.                 case SC_KEYMENU:
  208.                 case SC_MONITORPOWER:
  209.                         return 1;
  210.             }
  211.             break;
  212.         case WM_SYSKEYDOWN:
  213.             // Handle Alt+Enter to do mode-switching
  214.             if( VK_RETURN == wParam )
  215.             {
  216.                 SwitchDisplayModes( !m_bFullScreen, m_dwScreenWidth,
  217.                                     m_dwScreenHeight );
  218.             }
  219.             break;
  220.         case WM_LBUTTONDOWN:
  221.         case WM_RBUTTONDOWN:
  222.         case WM_KEYDOWN:
  223.             // Move from splash screen when user presses a key
  224.             if( m_dwAppState == APPSTATE_DISPLAYSPLASH )
  225.             {
  226.                 // Advance to the first level
  227.                 m_dwAppState = APPSTATE_BEGINLEVELSCREEN;
  228.                 DXUtil_Timer( TIMER_START );
  229.                 AdvanceLevel();
  230.                 return 0;
  231.             }
  232.             if( msg == WM_KEYDOWN ) 
  233.             {
  234.                 if( m_bDebugMode )
  235.                 {
  236.                     switch( wParam )
  237.                     {
  238.                         case 'N':
  239.                             // Reset ship position
  240.                             m_pShip->m_pSource->m_vCMPos      = D3DXVECTOR3( 10.0f, 15.0f, 3.0f );
  241.                             m_pShip->m_pSource->m_vAngularVel = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  242.                             m_pShip->m_pSource->m_vCMVel      = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  243.                             m_pShip->m_vEulerAngles           = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  244.                             break;
  245.                         case 'C': g_bDebugFreezeZoneRender = TRUE; break;
  246.                         case 'P': m_bPaused = !m_bPaused; break;
  247.                         case 'I': m_bWireMode = !m_bWireMode;   break;
  248.                         case 'G': g_Profile.bRenderGround = !g_Profile.bRenderGround; break;
  249.                         case 'Q': g_vDebugMove.y = 1.0f; break;
  250.                         case 'E': g_vDebugMove.y = -1.0f; break;
  251.                         case 'W': g_vDebugMove.x = 1.0f; break;
  252.                         case 'S': g_vDebugMove.x = -1.0f; break;
  253.                         case 'A': g_vDebugMove.z = 1.0f; break;
  254.                         case 'D': g_vDebugMove.z = -1.0f; break;
  255.                         case '1': g_vDebugRotate.x = 1.0f; break;
  256.                         case '2': g_vDebugRotate.x = -1.0f; break;
  257.                         case '3': g_vDebugRotate.y = 1.0f; break;
  258.                         case '4': g_vDebugRotate.y = -1.0f; break;
  259.                         case 'R': g_vDebugRotate.z = 1.0f; break;
  260.                         case 'F': g_vDebugRotate.z = -1.0f; break;
  261.                     }
  262.                 }
  263.             }
  264.             return 0;
  265.         case WM_KEYUP:
  266.             if( m_bDebugMode )
  267.             {
  268.                 switch( wParam )
  269.                 {
  270.                     case 'Q': g_vDebugMove.y = 0.0f; break;
  271.                     case 'E': g_vDebugMove.y = 0.0f; break;
  272.                     case 'W': g_vDebugMove.x = 0.0f; break;
  273.                     case 'S': g_vDebugMove.x = 0.0f; break;
  274.                     case 'A': g_vDebugMove.z = 0.0f; break;
  275.                     case 'D': g_vDebugMove.z = 0.0f; break;
  276.                     case '1': g_vDebugRotate.x = 0.0f; break;
  277.                     case '2': g_vDebugRotate.x = 0.0f; break;
  278.                     case '3': g_vDebugRotate.y = 0.0f; break;
  279.                     case '4': g_vDebugRotate.y = 0.0f; break;
  280.                     case 'R': g_vDebugRotate.z = 0.0f; break;
  281.                     case 'F': g_vDebugRotate.z = 0.0f; break;
  282.                 }
  283.             }
  284.             return 0;
  285.         case WM_PAINT:
  286.             if( m_bDisplayReady )
  287.             {
  288.                 switch( m_dwAppState )
  289.                 {
  290.                     case APPSTATE_DISPLAYSPLASH:
  291.                     {
  292.                         RenderSplash();
  293.                         g_pd3dDevice->Present( 0, 0, 0, 0 );
  294.                         break;
  295.                     }
  296.                     case APPSTATE_ACTIVE:
  297.                     {
  298.                         RenderFrame();
  299.                         g_pd3dDevice->Present( 0, 0, 0, 0 );
  300.                         break;
  301.                     }
  302.                 }
  303.             }
  304.             break;
  305.         case WM_DESTROY:
  306.             InvalidateDeviceObjects();
  307.             DeleteDeviceObjects();
  308.             FinalCleanup();
  309.             PostQuitMessage( 0 );
  310.             m_bDisplayReady = FALSE;
  311.             break;
  312.     }
  313.     return DefWindowProc( hWnd, msg, wParam, lParam );
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Name: OneTimeSceneInit()
  317. // Desc:
  318. //-----------------------------------------------------------------------------
  319. HRESULT CMyApplication::OneTimeSceneInit( HWND hWnd )
  320. {
  321.     HRESULT hr;
  322.     // Find the donuts4.ini file
  323.     if( FAILED( hr = FindMediaFileCch( m_strProfilePath, sizeof(m_strProfilePath)/sizeof(TCHAR), TEXT("donuts4.ini") ) ) )
  324.     {
  325.         CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, TEXT("donuts4.ini"), m_strProfilePath );
  326.         return DXTRACE_ERR( TEXT("FindMediaFileCch"), hr );
  327.     }
  328.     // Set the current working dir, so that the model loading 
  329.     // code in d3dfile.cpp can find the textures
  330.     lstrcpy( m_strCurrentWorkingDir, m_strProfilePath );
  331.     TCHAR* pChar = _tcsrchr( m_strCurrentWorkingDir, TEXT('\') );
  332.     if (pChar)
  333.         *pChar = 0;
  334.     SetCurrentDirectory( m_strCurrentWorkingDir );
  335.     // Read the ini file
  336.     g_Profile.GetProfile( m_strProfilePath );
  337.     // Watch this file to see if it changes.  If it does, reload everything
  338.     m_pFileWatch = new CFileWatch();
  339.     if( NULL == m_pFileWatch )
  340.         return E_OUTOFMEMORY;
  341.     m_pFileWatch->AddFileToWatch( m_strProfilePath );
  342.     // Watch the theme files as well
  343.     for( int iTheme=0; iTheme<g_Profile.nNumThemes; iTheme++ )
  344.         m_pFileWatch->AddFileToWatch( g_Profile.aThemes[iTheme].szFile );
  345.     m_pFileWatch->Start();
  346.     // Use settings read from g_Profile
  347.     m_bFullScreen   = g_Profile.bFullScreen;
  348.     if( g_Profile.bForceThemeSelect )
  349.         m_nCurTheme = g_Profile.nSelectTheme;
  350.     else
  351.         m_nCurTheme = rand() % g_Profile.nNumThemes;
  352.     // In fullscreen mode, keep the window hidden so that
  353.     // a blank window doesn't appear before d3d switches to fullscreen
  354.     if( !m_bFullScreen )
  355.         ShowWindow( m_hWndMain, SW_SHOW );
  356.     // Initialize the input stuff
  357.     m_pInputManager = new CInputManager( this );
  358.     if( NULL == m_pInputManager )
  359.         return E_OUTOFMEMORY;
  360.     m_pInputManager->OneTimeSceneInit( hWnd, &g_guidApp );
  361.     m_p3DDrawManager = new C3DDrawManager();
  362.     if( NULL == m_p3DDrawManager )
  363.         return E_OUTOFMEMORY;
  364.     g_p3DDrawManager = m_p3DDrawManager;
  365.     if( m_p3DDrawManager )
  366.         m_p3DDrawManager->OneTimeSceneInit();
  367.     // Initialize the audio stuff. Note: if this call fails, we can continue with no sound.
  368.     if( g_Profile.bLoadAudio )
  369.         CreateSoundObjects( hWnd );
  370.     // Initialize the display stuff
  371.     if( FAILED( hr = InitDeviceObjects( hWnd ) ) )
  372.         return hr;
  373.     // Construct the game menus
  374.     ConstructMenus();
  375.     // Initial program state is to display the splash screen
  376.     m_dwAppState = APPSTATE_LOADSPLASH;
  377.     return S_OK;
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Name: InitDeviceObjects()
  381. // Desc:
  382. //-----------------------------------------------------------------------------
  383. HRESULT CMyApplication::InitDeviceObjects( HWND hWnd )
  384. {
  385.     HRESULT hr;
  386.     // Construct a new display
  387.     LPDIRECT3D9 pD3D = Direct3DCreate9( D3D_SDK_VERSION );
  388.     if( NULL == pD3D )
  389.     {
  390.         CleanupAndDisplayError( DONUTSERR_NODIRECT3D, NULL, NULL );
  391.         return DXTRACE_ERR( TEXT("Direct3DCreate9"), E_FAIL );
  392.     }
  393.     // Get the current desktop format
  394.     pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &m_DesktopMode );
  395.     const D3DFORMAT fmtFullscreenArray[] = 
  396.     {
  397.         D3DFMT_A8R8G8B8,
  398.         D3DFMT_X8R8G8B8,
  399.         D3DFMT_X1R5G5B5,
  400.         D3DFMT_A1R5G5B5,
  401.         D3DFMT_R5G6B5,
  402.     };
  403.     const INT numFullscreenFmts = sizeof(fmtFullscreenArray) / sizeof(fmtFullscreenArray[0]);
  404.     INT iFmt;
  405.     // Find a pixel format that will be good for fullscreen back buffers
  406.     for( iFmt = 0; iFmt < numFullscreenFmts; iFmt++ )
  407.     {
  408.         if( SUCCEEDED( pD3D->CheckDeviceType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 
  409.             fmtFullscreenArray[iFmt], fmtFullscreenArray[iFmt], FALSE ) ) )
  410.         {
  411.             m_d3dfmtFullscreen = fmtFullscreenArray[iFmt];
  412.             break;
  413.         }
  414.     }
  415.     const D3DFORMAT fmtTextureArray[] = 
  416.     {
  417.         D3DFMT_A8R8G8B8,
  418.         D3DFMT_A4R4G4B4,
  419.         D3DFMT_A1R5G5B5,
  420.     };
  421.     const INT numTextureFmts = sizeof(fmtTextureArray) / sizeof(fmtTextureArray[0]);
  422.     // Find a format that is supported as a texture map for the current mode
  423.     for( iFmt = 0; iFmt < numTextureFmts; iFmt++ )
  424.     {
  425.         if( SUCCEEDED( pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 
  426.             m_DesktopMode.Format, 0, D3DRTYPE_TEXTURE, fmtTextureArray[iFmt] ) ) )
  427.         {
  428.             m_d3dfmtTexture = fmtTextureArray[iFmt];
  429.             break;
  430.         }
  431.     }
  432.     // Set up presentation parameters for the display
  433.     ZeroMemory( &m_d3dpp, sizeof(m_d3dpp) );
  434.     m_d3dpp.Windowed         = !m_bFullScreen;
  435.     m_d3dpp.BackBufferCount  = 1;
  436.     m_d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
  437.     m_d3dpp.EnableAutoDepthStencil = TRUE;
  438.     m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  439.     m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  440.     if( m_bFullScreen )
  441.     {
  442.         m_d3dpp.hDeviceWindow    = hWnd;
  443.         m_d3dpp.BackBufferWidth  = m_dwScreenWidth;
  444.         m_d3dpp.BackBufferHeight = m_dwScreenHeight;
  445.         m_d3dpp.BackBufferFormat = m_d3dfmtFullscreen;
  446.     }
  447.     else
  448.     {
  449.         m_d3dpp.BackBufferFormat = m_DesktopMode.Format;
  450.     }
  451.     D3DDEVTYPE dwDevType = D3DDEVTYPE_HAL;
  452.     DWORD dwBehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  453.     if( g_Profile.bForceREF )
  454.         dwDevType = D3DDEVTYPE_REF;
  455.     if( g_Profile.bForceSoftwareVP )
  456.         dwBehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  457.     if( g_Profile.bForceHardwareVP )
  458.         dwBehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  459.     // Create the device
  460.     hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, dwDevType, hWnd,
  461.                              dwBehaviorFlags, &m_d3dpp, &g_pd3dDevice );
  462.     pD3D->Release();
  463.     if( FAILED(hr) )
  464.     {
  465.         CleanupAndDisplayError( DONUTSERR_NOD3DDEVICE, NULL, NULL );
  466.         return DXTRACE_ERR( TEXT("pD3D->CreateDevice"), hr );
  467.     }
  468.     // Create some game fonts
  469.     m_pGameFont = new CD3DFont( _T("Tahoma"), 30, D3DFONT_BOLD );
  470.     if( NULL == m_pGameFont )
  471.         return E_OUTOFMEMORY;
  472.     m_pGameFont->InitDeviceObjects( g_pd3dDevice );
  473.     m_pMenuFont = new CD3DFont( _T("Impact"), 48, D3DFONT_BOLD );
  474.     if( NULL == m_pMenuFont )
  475.         return E_OUTOFMEMORY;
  476.     m_pMenuFont->InitDeviceObjects( g_pd3dDevice );
  477.     m_pMenuFont->RestoreDeviceObjects();
  478.     // Begin the scene
  479.     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
  480.     {
  481.         // Erase the screen
  482.         g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0L );
  483.         m_pMenuFont->DrawTextScaled( -1.0f, -0.5f, 0.9f, 0.10f, 0.10f, 
  484.                                      0xffffffff, _T("Loading. Please wait..."), D3DFONT_FILTERED|D3DFONT_CENTERED_X );
  485.         m_pMenuFont->DrawTextScaled( -0.5f, 0.5f, 0.9f, 0.05f, 0.05f, 
  486.                                      0xffffff00, _T("Controls:nMovement: Arrow keys or W,A,S,DnAim and fire: Mouse"), D3DFONT_FILTERED );
  487.         // End the scene
  488.         g_pd3dDevice->EndScene();
  489.     }
  490.     g_pd3dDevice->Present( 0, 0, 0, 0 );
  491.     m_pMenuFont->InvalidateDeviceObjects();
  492.     if( m_p3DDrawManager )
  493.         m_p3DDrawManager->InitDeviceObjects();
  494.     // Load the sky texture
  495.     TCHAR strFile[MAX_PATH];
  496.     FindMediaFileCch( strFile, MAX_PATH, g_Profile.aThemes[m_nCurTheme].Sky.szTextureMap );
  497.     // Create the texture using D3DX
  498.     if( FAILED( hr = D3DXCreateTextureFromFileEx( g_pd3dDevice, strFile, 
  499.                 D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, m_d3dfmtTexture, 
  500.                 D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 
  501.                 D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 0, NULL, NULL, &m_pSkyTexture ) ) )
  502.     {
  503.         CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.aThemes[m_nCurTheme].Sky.szTextureMap, strFile );
  504.         return DXTRACE_ERR( TEXT("D3DUtil_CreateTexture"), hr );
  505.     }
  506.     // Load UI texture 
  507.     FindMediaFileCch( strFile, MAX_PATH, g_Profile.szUITextureMap );
  508.     if( FAILED( hr = D3DXCreateTextureFromFileEx( g_pd3dDevice, strFile, 
  509.                         D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, m_d3dfmtTexture, 
  510.                         D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 
  511.                         D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 0, NULL, NULL, &m_pUITexture ) ) ) 
  512.     {
  513.         CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.szUITextureMap, strFile );
  514.         return DXTRACE_ERR( TEXT("D3DXCreateTextureFromFileEx"), hr );
  515.     }
  516.     // Load splash texture 
  517.     FindMediaFileCch( strFile, MAX_PATH, g_Profile.szSplashTextureMap );
  518.     if( FAILED( hr = D3DXCreateTextureFromFileEx( g_pd3dDevice, strFile, 
  519.                             D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, m_d3dfmtTexture, 
  520.                             D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 
  521.                             D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 0, NULL, NULL, &m_pSplashTexture ) ) ) 
  522.     {
  523.         CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.szSplashTextureMap, strFile );
  524.         return DXTRACE_ERR( TEXT("D3DXCreateTextureFromFileEx"), hr );
  525.     }
  526.     // Load particle texture
  527.     FindMediaFileCch( strFile, MAX_PATH, g_Profile.Blaster.szParticleTextureMap );
  528.     if( FAILED( hr = D3DXCreateTextureFromFileEx( g_pd3dDevice, strFile, 
  529.                 D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, 
  530.                 D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 
  531.                 D3DX_FILTER_TRIANGLE|D3DX_FILTER_MIRROR, 0, NULL, NULL, &g_Profile.Blaster.pParticleTexture ) ) )
  532.     {
  533.         CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.Blaster.szParticleTextureMap, strFile );
  534.         return DXTRACE_ERR( TEXT("D3DUtil_CreateTexture"), hr );
  535.     }
  536.     // Load sky dome mesh
  537.     m_pSkyDome = new CD3DMesh();
  538.     if( m_pSkyDome )
  539.     {
  540.         FindMediaFileCch( strFile, MAX_PATH, g_Profile.aThemes[m_nCurTheme].Sky.szModel );
  541.         if( FAILED( hr = m_pSkyDome->Create( g_pd3dDevice, strFile ) ) )
  542.         {
  543.             CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.aThemes[m_nCurTheme].Sky.szModel, strFile );
  544.             return DXTRACE_ERR( TEXT("m_pSkyDome->Create"), hr );
  545.         }
  546.         m_pSkyDome->m_bUseMaterials = FALSE;
  547.     }
  548.     // Create a vextex buffer for the viewport
  549.     if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof(SCREENVERTEX),
  550.                                        D3DUSAGE_WRITEONLY, D3DFVF_SCREENVERTEX,
  551.                                        D3DPOOL_MANAGED, &m_pViewportVB, NULL ) ) )
  552.         return DXTRACE_ERR( TEXT("g_pd3dDevice->CreateVertexBuffer"), hr );
  553.     // Create a vextex buffer for the radar
  554.     if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof(SCREENVERTEX),
  555.                                        D3DUSAGE_WRITEONLY, D3DFVF_SCREENVERTEX,
  556.                                        D3DPOOL_MANAGED, &m_pRadarVB, NULL ) ) )
  557.         return DXTRACE_ERR( TEXT("g_pd3dDevice->CreateVertexBuffer"), hr );
  558.     // Load the enemy models
  559.     for( int iEnemy=0; iEnemy<g_Profile.nNumEnemies; iEnemy++ )
  560.     {
  561.         C3DModel* pModel = new C3DModel();
  562.         if( pModel )
  563.         {
  564.             pModel->OneTimeSceneInit();
  565.             FindMediaFileCch( strFile, MAX_PATH, g_Profile.aEnemyStyles[iEnemy].strEnemyModel );
  566.             if( FAILED( hr = pModel->InitDeviceObjects( strFile, (g_Profile.aEnemyStyles[iEnemy].EnemyCreationType == ECT_CreateTest), 0.8f ) ) )
  567.             {
  568.                 SAFE_DELETE( pModel );
  569.                 CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.aEnemyStyles[iEnemy].strEnemyModel, strFile );
  570.                 return DXTRACE_ERR( TEXT("pModel->InitDeviceObjects"), hr );
  571.             }
  572.             g_Profile.aEnemyStyles[iEnemy].pModel = pModel;
  573.         }
  574.     }
  575.     // Load the bullet models
  576.     {
  577.         C3DModel* pModel = new C3DModel();
  578.         if( pModel )
  579.         {
  580.             pModel->OneTimeSceneInit();
  581.             FindMediaFileCch( strFile, MAX_PATH, g_Profile.Blaster.strBulletModel );
  582.             if( FAILED( hr = pModel->InitDeviceObjects( strFile, false, 1.2f ) ) ) 
  583.             {
  584.                 SAFE_DELETE( pModel );
  585.                 CleanupAndDisplayError( DONUTSERR_ARTLOADFAILED, g_Profile.Blaster.strBulletModel, strFile );
  586.                 return DXTRACE_ERR( TEXT("pModel->InitDeviceObjects"), hr );
  587.             }
  588.             if( pModel->m_pMesh )
  589.                 pModel->m_pMesh->UseMeshMaterials(false);
  590.             g_Profile.Blaster.pModel = pModel;
  591.         }
  592.     }
  593.     m_pShipModel = new C3DModel();
  594.     if( NULL == m_pShipModel )
  595.         return DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY );
  596.     m_pShipModel->m_vBoundingMin = D3DXVECTOR3(-2.9f,-2.9f,-2.9f);
  597.     m_pShipModel->m_vBoundingMax = D3DXVECTOR3( 2.9f,2.9f, 2.9f);
  598.     m_pShipModel->m_fRadius      = sqrtf(2.0f);
  599.     m_pShipModel->m_vBoundingVertex[0] = D3DXVECTOR3( m_pShipModel->m_vBoundingMin.x, m_pShipModel->m_vBoundingMin.y, m_pShipModel->m_vBoundingMin.z ); // xyz
  600.     m_pShipModel->m_vBoundingVertex[1] = D3DXVECTOR3( m_pShipModel->m_vBoundingMax.x, m_pShipModel->m_vBoundingMin.y, m_pShipModel->m_vBoundingMin.z ); // Xyz
  601.     m_pShipModel->m_vBoundingVertex[2] = D3DXVECTOR3( m_pShipModel->m_vBoundingMin.x, m_pShipModel->m_vBoundingMax.y, m_pShipModel->m_vBoundingMin.z ); // xYz
  602.     m_pShipModel->m_vBoundingVertex[3] = D3DXVECTOR3( m_pShipModel->m_vBoundingMax.x, m_pShipModel->m_vBoundingMax.y, m_pShipModel->m_vBoundingMin.z ); // XYz
  603.     m_pShipModel->m_vBoundingVertex[4] = D3DXVECTOR3( m_pShipModel->m_vBoundingMin.x, m_pShipModel->m_vBoundingMin.y, m_pShipModel->m_vBoundingMax.z ); // xyZ
  604.     m_pShipModel->m_vBoundingVertex[5] = D3DXVECTOR3( m_pShipModel->m_vBoundingMax.x, m_pShipModel->m_vBoundingMin.y, m_pShipModel->m_vBoundingMax.z ); // XyZ
  605.     m_pShipModel->m_vBoundingVertex[6] = D3DXVECTOR3( m_pShipModel->m_vBoundingMin.x, m_pShipModel->m_vBoundingMax.y, m_pShipModel->m_vBoundingMax.z ); // xYZ
  606.     m_pShipModel->m_vBoundingVertex[7] = D3DXVECTOR3( m_pShipModel->m_vBoundingMax.x, m_pShipModel->m_vBoundingMax.y, m_pShipModel->m_vBoundingMax.z ); // XYZ
  607.     // Load terrain textures and meshes
  608.     g_pTerrain = new CTerrainEngine( this );
  609.     if( g_pTerrain )
  610.     {
  611.         hr = g_pTerrain->OneTimeSceneInit( &g_Profile.aThemes[m_nCurTheme] );
  612.         if( FAILED(hr) )
  613.             return DXTRACE_ERR( TEXT("g_pTerrain->OneTimeSceneInit"), hr );
  614.         hr = g_pTerrain->InitDeviceObjects( m_d3dfmtTexture );
  615.         if( FAILED(hr) )
  616.             return DXTRACE_ERR( TEXT("g_pTerrain->InitDeviceObjects"), hr );
  617.     }
  618.     // Add a ship to the displaylist
  619.     m_pShip = new CPlayerShip();
  620.     if( NULL == m_pShip )
  621.         return DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY );
  622.     D3DXMATRIX mOrientation;
  623.     D3DXMatrixIdentity( &mOrientation );
  624.     D3DXVECTOR3 vPos;
  625.     vPos.x = rnd(0.0f,1.0f)*ZONE_WIDTH*g_pTerrain->m_dwWorldWidth;
  626.     vPos.z = rnd(0.0f,1.0f)*ZONE_HEIGHT*g_pTerrain->m_dwWorldHeight;   
  627.     vPos.y = g_pTerrain->GetHeight( vPos.x, vPos.z ) + 10.0f;
  628.     m_pShip->OneTimeSceneInit( 0, vPos, &mOrientation, m_pShipModel );
  629.     m_pShip->InitDeviceObjects();
  630.     if( g_pTerrain )
  631.         g_pTerrain->AddDisplayObject( m_pShip );
  632.     // Now that all the display objects are created, "restore" them (create
  633.     // local mem objects and set state)
  634.     if( FAILED( hr = RestoreDeviceObjects() ) )
  635.         return DXTRACE_ERR( TEXT("RestoreDeviceObjects"), hr );
  636.     // The display is now ready
  637.     m_bDisplayReady = TRUE;
  638.     return S_OK;
  639. }
  640. //-----------------------------------------------------------------------------
  641. // Name: RestoreDeviceObjects()
  642. // Desc:
  643. //-----------------------------------------------------------------------------
  644. HRESULT CMyApplication::RestoreDeviceObjects()
  645. {
  646.     HRESULT hr;
  647.     HWND hWnd = m_hWndMain;
  648.     if( FALSE == m_bFullScreen )
  649.     {
  650.         // If we are still a WS_POPUP window we should convert to a normal app
  651.         // window so we look like a windows app.
  652.         DWORD dwStyle  = GetWindowStyle( hWnd );
  653.         dwStyle &= ~WS_POPUP;
  654.         dwStyle |= WS_CAPTION | WS_MINIMIZEBOX;
  655.         SetWindowLong( hWnd, GWL_STYLE, dwStyle );
  656.         // Set window size
  657.         RECT rc;
  658.         SetRect( &rc, 0, 0, 640, 480 );
  659.         SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  660.                       SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
  661.         SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  662.                       SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
  663.         //  Make sure our window does not hang outside of the work area
  664.         RECT rcWork;
  665.         SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
  666.         GetWindowRect( hWnd, &rc );
  667.         if( rc.left < rcWork.left ) rc.left = rcWork.left;
  668.         if( rc.top  < rcWork.top )  rc.top  = rcWork.top;
  669.         SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0,
  670.                       SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  671.     }
  672.     if( m_p3DDrawManager )
  673.         m_p3DDrawManager->RestoreDeviceObjects();
  674.     // Create the device-dependent objects for the file-based mesh objects
  675.     if( m_pSkyDome )
  676.     {
  677.         if( FAILED( hr = m_pSkyDome->RestoreDeviceObjects( g_pd3dDevice ) ) )
  678.             return DXTRACE_ERR( TEXT("m_pSkyDome->RestoreDeviceObjects"), hr );
  679.     }
  680.     if( g_pTerrain )        
  681.     {
  682.         if( FAILED( hr = g_pTerrain->RestoreDeviceObjects( m_hWndMain ) ) )
  683.             return DXTRACE_ERR( TEXT("g_pTerrain->RestoreDeviceObjects"), hr );
  684.     }
  685.     if( m_pGameFont )
  686.     {
  687.         if( FAILED( hr = m_pGameFont->RestoreDeviceObjects() ) )
  688.             return DXTRACE_ERR( TEXT("m_pGameFont->RestoreDeviceObjects"), hr );
  689.     }
  690.     if( m_pMenuFont )
  691.     {
  692.         if( FAILED( hr = m_pMenuFont->RestoreDeviceObjects() ) )
  693.             return DXTRACE_ERR( TEXT("m_pMenuFont->RestoreDeviceObjects"), hr );
  694.     }
  695.     // Get viewport dimensions
  696.     D3DVIEWPORT9 vp;
  697.     g_pd3dDevice->GetViewport(&vp);
  698.     FLOAT sx = (FLOAT)vp.Width;
  699.     FLOAT sy = (FLOAT)vp.Height;
  700.     if( m_pViewportVB )
  701.     {
  702.         // Setup dimensions for the viewport covering square
  703.         SCREENVERTEX* v;
  704.         m_pViewportVB->Lock( 0, 0, (void**)&v, 0 );
  705.         v[0].color = v[1].color = v[2].color = v[3].color = 0xFFFFFFFF;
  706.         v[0].p = D3DXVECTOR4( 0,sy,0.0f,1.0f);
  707.         v[0].tu = 0.0f;  v[0].tv = 1.0f; 
  708.         v[1].p = D3DXVECTOR4( 0, 0,0.0f,1.0f);
  709.         v[1].tu = 0.0f;  v[1].tv = 0.0f; 
  710.         v[2].p = D3DXVECTOR4(sx,sy,0.0f,1.0f);
  711.         v[2].tu = 1.0f;  v[2].tv = 1.0f; 
  712.         v[3].p = D3DXVECTOR4(sx, 0,0.0f,1.0f);
  713.         v[3].tu = 1.0f;  v[3].tv = 0.0f; 
  714.         m_pViewportVB->Unlock();
  715.     }
  716.     m_fRadarTextureX = 0.20f*(float)vp.Height;
  717.     m_fRadarTextureY = 0.20f*(float)vp.Height;
  718.     // Create a texture for the radar overlay
  719.     UINT x,y;
  720.     x = (UINT) m_fRadarTextureX;
  721.     y = (UINT) m_fRadarTextureY;
  722.     D3DFORMAT f = m_d3dfmtTexture;
  723.     D3DXCheckTextureRequirements( g_pd3dDevice, &x, &y, NULL, 0, &f, D3DPOOL_MANAGED );
  724.     hr = D3DXCreateTexture( g_pd3dDevice, x, y, 1, 0, 
  725.                             m_d3dfmtTexture, D3DPOOL_MANAGED, &m_pRadarTexture );
  726.     if( FAILED(hr) )
  727.         return DXTRACE_ERR( TEXT("D3DXCreateTexture"), hr );
  728.     // Create a radar texture that's on a scratch surface w/ a known format & size
  729.     hr = D3DXCreateTexture( g_pd3dDevice, 256, 256, 1, 0, 
  730.                             D3DFMT_A4R4G4B4, D3DPOOL_SCRATCH, 
  731.                             &m_pTempRadarTexture );
  732.     if( FAILED(hr) )
  733.         return DXTRACE_ERR( TEXT("D3DXCreateTexture"), hr );
  734.     D3DSURFACE_DESC desc;
  735.     m_pTempRadarTexture->GetLevelDesc( 0, &desc ); 
  736.     if( desc.Height != 256 ||
  737.         desc.Width  != 256 ||
  738.         desc.Format != D3DFMT_A4R4G4B4 )
  739.     {
  740.         // Expect texture made in scratch surface to be what we ask for
  741.         if( FAILED(hr) )
  742.             return DXTRACE_ERR( TEXT("D3DXCreateTexture"), hr );
  743.     }
  744.     if( m_pRadarVB )
  745.     {
  746.         // Setup dimensions for the radar covering sqaure
  747.         SCREENVERTEX* v;
  748.         FLOAT x = 0.095f*sx;
  749.         FLOAT y = 0.14f*sy;
  750.         m_pRadarVB->Lock( 0, 0, (void**)&v, 0 );
  751.         v[0].color = v[1].color = v[2].color = v[3].color = 0xFFFFFFFF;
  752.         v[0].p = D3DXVECTOR4( x,m_fRadarTextureY+y,0.0f,1.0f);
  753.         v[0].tu = 0.0f;  v[0].tv = 1.0f; 
  754.         v[1].p = D3DXVECTOR4( x, y,0.0f,1.0f);
  755.         v[1].tu = 0.0f;  v[1].tv = 0.0f; 
  756.         v[2].p = D3DXVECTOR4(m_fRadarTextureX+x,m_fRadarTextureY+y,0.0f,1.0f);
  757.         v[2].tu = 1.0f;  v[2].tv = 1.0f; 
  758.         v[3].p = D3DXVECTOR4(m_fRadarTextureX+x, y,0.0f,1.0f);
  759.         v[3].tu = 1.0f;  v[3].tv = 0.0f; 
  760.         m_pRadarVB->Unlock();
  761.     }
  762.     // Set up the camera
  763.     D3DXVECTOR3 vAt = D3DXVECTOR3(0.0f,0.0f,0.0f);
  764.     D3DXVECTOR3 vLookAt = D3DXVECTOR3(0.0f,0.0f,1.0f);
  765.     D3DXVECTOR3 vUp = D3DXVECTOR3(0.0f,1.0f,0.0f);
  766.     
  767.     m_Camera.SetViewParams( vAt, vLookAt, vUp );
  768.     m_Camera.SetProjParams( g_Profile.fFOV, 1.0f, 0.01f, 250.0f ); // 200.0f );
  769.     // Set up default matrices (using the CD3DCamera class)
  770.     D3DXMATRIX mView = m_Camera.GetViewMatrix();
  771.     D3DXMATRIX mProj = m_Camera.GetProjMatrix();
  772.     g_pd3dDevice->SetTransform( D3DTS_VIEW,       &mView );
  773.     g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProj );
  774.     for( int iLight=0; iLight<g_Profile.aThemes[m_nCurTheme].nNumLights; iLight++ )
  775.     {
  776.         // Set up lighting states
  777.         D3DLIGHT9 light;
  778.         ZeroMemory( &light, sizeof(D3DLIGHT9) );
  779.         light.Type        = D3DLIGHT_DIRECTIONAL;
  780.         D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &g_Profile.aThemes[m_nCurTheme].aLights[iLight].vDirection );
  781.         light.Diffuse.r   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vDiffuse.x;
  782.         light.Diffuse.g   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vDiffuse.y;
  783.         light.Diffuse.b   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vDiffuse.z;
  784.         light.Ambient.r   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vAmbient.x;
  785.         light.Ambient.g   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vAmbient.y;
  786.         light.Ambient.b   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vAmbient.z;
  787.         light.Specular.r   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vSpecular.x;
  788.         light.Specular.g   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vSpecular.y;
  789.         light.Specular.b   = g_Profile.aThemes[m_nCurTheme].aLights[iLight].vSpecular.z;
  790.         g_pd3dDevice->SetLight( iLight, &light );
  791.         g_pd3dDevice->LightEnable( iLight, TRUE );
  792.     }
  793.     // Disable the rest of the light states
  794.     g_pd3dDevice->LightEnable( g_Profile.aThemes[m_nCurTheme].nNumLights, FALSE );
  795.     // Set miscellaneous render states
  796.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  797.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  798.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  799.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  800.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  801.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  802.     // Set fog render states
  803.     FLOAT fFogStart     = g_Profile.fFogStart; 
  804.     FLOAT fFogEnd       = g_Profile.fFogEnd; 
  805.     FLOAT fFogDensity   = 1.0f;
  806.     g_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,      TRUE );
  807.     g_pd3dDevice->SetRenderState( D3DRS_FOGCOLOR,       g_Profile.aThemes[m_nCurTheme].Sky.dwFogColor );
  808.     g_pd3dDevice->SetRenderState( D3DRS_FOGVERTEXMODE,  D3DFOG_LINEAR );
  809.     g_pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE,   D3DFOG_NONE );
  810.     g_pd3dDevice->SetRenderState( D3DRS_FOGSTART,       *((DWORD*) (&fFogStart)) );
  811.     g_pd3dDevice->SetRenderState( D3DRS_FOGEND,         *((DWORD*) (&fFogEnd)) );
  812.     g_pd3dDevice->SetRenderState( D3DRS_FOGDENSITY,     *((DWORD*) (&fFogDensity)) );
  813.     // Restore the enemy models
  814.     for( int iEnemy=0; iEnemy<g_Profile.nNumEnemies; iEnemy++ )
  815.     {
  816.         C3DModel* pModel = g_Profile.aEnemyStyles[iEnemy].pModel;
  817.         if( pModel )
  818.             pModel->RestoreDeviceObjects();
  819.     }
  820.     C3DModel* pModel = g_Profile.Blaster.pModel;
  821.     if( pModel )
  822.         pModel->RestoreDeviceObjects();
  823.     return S_OK;
  824. }
  825. //-----------------------------------------------------------------------------
  826. // Name: UpdateScene()
  827. // Desc:
  828. //-----------------------------------------------------------------------------
  829. HRESULT CMyApplication::UpdateScene()
  830. {
  831.     switch( m_dwAppState )
  832.     {
  833.         case APPSTATE_LOADSPLASH:
  834.             if( g_Profile.bRenderSplash )
  835.             {
  836.                 // Set the app state to displaying splash
  837.                 m_dwAppState = APPSTATE_DISPLAYSPLASH;
  838.             }
  839.             else
  840.             {
  841.                 m_dwAppState = APPSTATE_BEGINACTIVESCREEN;
  842.                 DXUtil_Timer( TIMER_START );
  843.                 AdvanceLevel();
  844.             }
  845.             break;
  846.         case APPSTATE_DISPLAYSPLASH:
  847.             // Nothing to do here, but wait for a WM_KEYDOWN or button click to 
  848.             // carry us to APPSTATE_BEGINLEVELSCREEN
  849.             break;
  850.         case APPSTATE_BEGINLEVELSCREEN:
  851.             if( m_pMusicScript )
  852.             {
  853.                 m_pMusicScript->SetVariableNumber("Level",m_dwLevel);
  854.                 m_pMusicScript->CallRoutine("AdvanceLevel");
  855.             }
  856.             DXUtil_Timer( TIMER_RESET );
  857.             m_dwAppState = APPSTATE_DISPLAYLEVELSCREEN;
  858.             break;
  859.         case APPSTATE_DISPLAYLEVELSCREEN:           
  860.             if( m_pInputManager )
  861.                 m_pInputManager->UpdateInput();
  862.             // Should never happen because segment lyric should trigger first.
  863.             if( DXUtil_Timer( TIMER_GETAPPTIME ) > 4.0f )
  864.             {
  865.                 m_dwAppState = APPSTATE_BEGINACTIVESCREEN;
  866.             }
  867.             break;
  868.         case APPSTATE_BEGINACTIVESCREEN:            
  869.             SCREENVERTEX* v;
  870.             if( m_pViewportVB )
  871.             {
  872.                 m_pViewportVB->Lock( 0, 0, (void**)&v, 0 );
  873.                 v[0].color = v[1].color = v[2].color = v[3].color = 0xFFFFFFFF;
  874.                 m_pViewportVB->Unlock();
  875.             }
  876.             if( m_pMusicScript && g_pTerrain )
  877.             {
  878.                 m_pMusicScript->SetVariableNumber("ObjectCount",g_pTerrain->m_dwEnemyCount);
  879.                 m_pMusicScript->CallRoutine("ExplodeObject");
  880.             }
  881.             m_dwAppState = APPSTATE_ACTIVE;
  882.             if( m_pMusicScript )
  883.                 m_pMusicScript->CallRoutine("StartLevel");
  884.             break;
  885.         case APPSTATE_ACTIVE:
  886.             FrameMove();
  887.             if( g_pTerrain && g_pTerrain->GetEnemyCount() == 0 )
  888.             {
  889.                 if( m_pMusicScript )
  890.                 {
  891.                     m_pMusicScript->CallRoutine("EndLevel");
  892.                     m_dwAppState = APPSTATE_WAITFORMUSICEND;
  893.                 }
  894.                 else
  895.                 {
  896.                     m_dwAppState = APPSTATE_TRIGGERLEVELSCREEN;
  897.                 }                   
  898.             }
  899.             break;
  900.         case APPSTATE_WAITFORMUSICEND:
  901.             // An "AdvanceLevel" lyric will come in via the DirectMusic notification tool
  902.             // and then state will be changed to APPSTATE_TRIGGERLEVELSCREEN
  903.             FrameMove();
  904.             break;
  905.         case APPSTATE_TRIGGERLEVELSCREEN:
  906.             FrameMove();
  907.             AdvanceLevel();
  908.             m_dwAppState = APPSTATE_BEGINLEVELSCREEN;
  909.             break;
  910.     }
  911.     return S_OK;
  912. }
  913. //-----------------------------------------------------------------------------
  914. // Name: FrameMove()
  915. // Desc:
  916. //-----------------------------------------------------------------------------
  917. VOID CMyApplication::FrameMove()
  918. {
  919.     m_fElapsedTime = DXUtil_Timer( TIMER_GETELAPSEDTIME );
  920.     m_fTime = DXUtil_Timer( TIMER_GETAPPTIME );
  921.     BOOL bPhysicsSimRan = FALSE;
  922.     // Update input from the joystick/keyboard/etc
  923.     if( m_pInputManager )
  924.         m_pInputManager->UpdateInput();
  925.     
  926.     if( m_p3DDrawManager )
  927.         m_p3DDrawManager->FrameMove( m_fElapsedTime );
  928.     // Check for game menu condition
  929.     if( m_pCurrentMenu )
  930.     {
  931.         UpdateMenus();
  932.         return;
  933.     }
  934.     UpdateFarthestAudioPath();
  935.     // Run the physics simulator at 60Hz
  936.     if( g_pTerrain )
  937.     {
  938.         FLOAT fDeltaToSimulate;
  939.         FLOAT fTimeToSimulate = m_fElapsedTime + m_fPhysicsSimCaryyOver;
  940.         fDeltaToSimulate = 1.0f/60.0f;
  941.         while( fTimeToSimulate > fDeltaToSimulate )
  942.         {
  943.             fDeltaToSimulate = 1.0f/60.0f;
  944.             bPhysicsSimRan = TRUE;
  945.             // This simulator runs at a constant 60Hz without 
  946.             // even if there's penetration, so its not very accurate
  947.             // but it is good enough for this simple game
  948.             g_pTerrain->FrameMove( fDeltaToSimulate );
  949.             fTimeToSimulate -= fDeltaToSimulate;
  950.         }
  951.         m_fPhysicsSimCaryyOver = fTimeToSimulate;
  952.     }
  953.     // If the physics advanced 
  954.     if( bPhysicsSimRan )
  955.     {
  956.         // Update the view
  957.         if( m_pShip )
  958.         {
  959.             D3DXVECTOR3 vEyePt;
  960.             D3DXVECTOR3 vLookatPt;
  961.             D3DXVECTOR3 vUpVec;
  962.             m_pShip->GetViewParams( &vEyePt, &vLookatPt, &vUpVec );
  963.             m_Camera.SetViewParams( vEyePt, vLookatPt, vUpVec );
  964.             // Update the cull info now that the camera has changed
  965.             D3DXMATRIXA16 mView = m_Camera.GetViewMatrix();
  966.             D3DXMATRIXA16 mProj = m_Camera.GetProjMatrix();
  967.             UpdateCullInfo( &m_cullinfo, &mView, &mProj );
  968.         }
  969. /*
  970.         // Update the audio paths
  971.         DWORD dwX;
  972.         for (dwX = 0; dwX < MAX_AUDIOPATHS; dwX++)
  973.         {
  974.             // Find the paths that are replacements and restart the sounds
  975.             C3DAudioPath* pAudioPath = &m_AudioPath[dwX];
  976.             if( pAudioPath != NULL && pAudioPath->m_pPath != NULL && pAudioPath->m_bReplaceSound)
  977.             {
  978.                 // Stop the playback of all segments on the path (who know what the script
  979.                 // has playing on this path...)
  980.                 m_pMusicManager->GetPerformance()->StopEx(pAudioPath->m_pPath,0,0);
  981.                 pAudioPath->m_bReplaceSound = FALSE;
  982.                 // Deactivate the path. This ensures that all audio in the buffer is cleared. 
  983.                 pAudioPath->m_pPath->Activate(FALSE);
  984.                 if (pAudioPath->m_pObject && m_pMusicScript )
  985.                 {
  986.                     // The script will need the audiopath to play on.
  987.                     m_pMusicScript->SetVariableObject("AudioPath",pAudioPath->m_pPath);
  988.                     // Reactivate the path before starting playback.
  989.                     pAudioPath->m_pPath->Activate(TRUE);
  990.                     // Depending on the object type, call the appropriate script.
  991.                     switch (pAudioPath->m_pObject->m_ObjectType)
  992.                     {
  993.                     case OBJ_ENEMY:
  994.                         m_pMusicScript->CallRoutine("PlayCube");
  995.                         break;
  996.                     }
  997.                 }
  998.             }
  999.             // Now, position the object in 3D space.
  1000.             if (pAudioPath->m_pObject && pAudioPath->m_pPath)
  1001.             {
  1002.                 // Get the 3d buffer interface from the audiopath and set it's params
  1003.                 IDirectSound3DBuffer* pBuffer;
  1004.                 if( SUCCEEDED( pAudioPath->m_pPath->GetObjectInPath( DMUS_PCHANNEL_ALL,DMUS_PATH_BUFFER, 0,
  1005.                                                                      GUID_NULL, 0, IID_IDirectSound3DBuffer, 
  1006.                                                                      (void **) &pBuffer ) ) )
  1007.                 {
  1008.                     DS3DBUFFER DS3DBuffer;
  1009.                     DS3DBuffer.dwInsideConeAngle = 360;
  1010.                     DS3DBuffer.dwMode = DS3DMODE_NORMAL;
  1011.                     DS3DBuffer.dwOutsideConeAngle = 360;
  1012.                     DS3DBuffer.dwSize = sizeof(DS3DBuffer);
  1013.                     DS3DBuffer.flMaxDistance = 10.0f;     
  1014.                     DS3DBuffer.flMinDistance = 1.0f;
  1015.                     DS3DBuffer.lConeOutsideVolume = 0;
  1016.                     DS3DBuffer.vConeOrientation = D3DXVECTOR3(0.0f,0.0f,1.0f);
  1017.                     DS3DBuffer.vPosition = pAudioPath->m_pObject->m_vPos;
  1018.                     DS3DBuffer.vVelocity = D3DXVECTOR3(0,0,0);
  1019.                     if( pAudioPath->m_pObject->m_ObjectType == OBJ_ENEMY )
  1020.                     {
  1021.                         C3DDisplayObject* p3DDisplayObject = (C3DDisplayObject*) pAudioPath->m_pObject;
  1022.                         DS3DBuffer.vVelocity = p3DDisplayObject->m_pSource->m_vCMVel;
  1023.                     }
  1024.                     pBuffer->SetAllParameters( &DS3DBuffer, DS3D_IMMEDIATE );
  1025.                     pBuffer->Release();
  1026.                 }
  1027.             }
  1028.         }
  1029. */
  1030.         RenderRadarTexture();
  1031.     }
  1032.     // Convert speed and thrust into integers that can be passed to the music script
  1033.     static long slLastThrust = 0;
  1034.     long lSpeed = (long) (D3DXVec3Length(&m_pShip->m_pSource->m_vCMVel) * 100);
  1035.     long lThrust = (long) g_pUserInput->fAxisMoveUD;
  1036.     // If the speed changed, then set the frequency of the engine based on the speed
  1037.     if( m_pEnginePath && lSpeed != m_lSpeed)
  1038.     {
  1039.         // Get the dsound buffer from the m_pEnginePath audiopath, 
  1040.         // and set its frequency based on the current speed
  1041.         IDirectSoundBuffer *pBuffer;
  1042.         if( SUCCEEDED( m_pEnginePath->GetObjectInPath( DMUS_PCHANNEL_ALL,DMUS_PATH_BUFFER,0,
  1043.                             GUID_NULL, 0, IID_IDirectSoundBuffer, (void **) &pBuffer ) ) )
  1044.         {
  1045.             pBuffer->SetFrequency( (DWORD) 22050 + (lSpeed * 200) );
  1046.             SAFE_RELEASE( pBuffer );
  1047.         }
  1048.         m_lSpeed = lSpeed;
  1049.     }
  1050.     // Tell the audio script if the thrust changed
  1051.     if( m_pMusicScript && lThrust != slLastThrust)
  1052.     {
  1053.         if (lThrust > 0)
  1054.             m_pMusicScript->CallRoutine("ThrustForward");
  1055.         else if (lThrust < 0)
  1056.             m_pMusicScript->CallRoutine("ThrustReverse");
  1057.         else 
  1058.             m_pMusicScript->CallRoutine("ThrustOff");
  1059.         slLastThrust = lThrust;
  1060.     }
  1061.     // Set the listener orientation
  1062.     if( m_p3DListener )
  1063.     {
  1064.         // Listener Parameters
  1065.         DS3DLISTENER dsListener;
  1066.         dsListener.dwSize = sizeof(dsListener);
  1067.         //Get the current 3D Parameters
  1068.         m_p3DListener->GetAllParameters(&dsListener);
  1069.         //Update the ship information
  1070.         dsListener.vPosition    = m_Camera.GetEyePt();
  1071.         dsListener.vVelocity    = m_pShip->m_pSource->m_vCMVel;
  1072.         dsListener.vOrientFront = m_Camera.GetViewDir();
  1073.         dsListener.vOrientTop   = m_Camera.GetUpVec();
  1074.         //Set the Parameters
  1075.         m_p3DListener->SetAllParameters(&dsListener,DS3D_IMMEDIATE);
  1076.     }
  1077. }
  1078. //-----------------------------------------------------------------------------
  1079. // Name: UpdateCullInfo()
  1080. // Desc: Sets up the frustum planes, endpoints, and center for the frustum
  1081. //       defined by a given view matrix and projection matrix.  This info will 
  1082. //       be used when culling each object in CullObject().
  1083. //-----------------------------------------------------------------------------
  1084. VOID CMyApplication::UpdateCullInfo( CULLINFO* pCullInfo, D3DXMATRIXA16* pMatView, 
  1085.                                      D3DXMATRIXA16* pMatProj )
  1086. {
  1087.     D3DXMATRIXA16 mat;
  1088.     D3DXMatrixMultiply( &mat, pMatView, pMatProj );
  1089.     D3DXMatrixInverse( &mat, NULL, &mat );
  1090.     pCullInfo->vecFrustum[0] = D3DXVECTOR3(-1.0f, -1.0f,  0.0f); // xyz
  1091.     pCullInfo->vecFrustum[1] = D3DXVECTOR3( 1.0f, -1.0f,  0.0f); // Xyz
  1092.     pCullInfo->vecFrustum[2] = D3DXVECTOR3(-1.0f,  1.0f,  0.0f); // xYz
  1093.     pCullInfo->vecFrustum[3] = D3DXVECTOR3( 1.0f,  1.0f,  0.0f); // XYz
  1094.     pCullInfo->vecFrustum[4] = D3DXVECTOR3(-1.0f, -1.0f,  1.0f); // xyZ
  1095.     pCullInfo->vecFrustum[5] = D3DXVECTOR3( 1.0f, -1.0f,  1.0f); // XyZ
  1096.     pCullInfo->vecFrustum[6] = D3DXVECTOR3(-1.0f,  1.0f,  1.0f); // xYZ
  1097.     pCullInfo->vecFrustum[7] = D3DXVECTOR3( 1.0f,  1.0f,  1.0f); // XYZ
  1098.     for( INT i = 0; i < 8; i++ )
  1099.         D3DXVec3TransformCoord( &pCullInfo->vecFrustum[i], &pCullInfo->vecFrustum[i], &mat );
  1100.     D3DXPlaneFromPoints( &pCullInfo->planeFrustum[0], &pCullInfo->vecFrustum[0], 
  1101.         &pCullInfo->vecFrustum[1], &pCullInfo->vecFrustum[2] ); // Near
  1102.     D3DXPlaneFromPoints( &pCullInfo->planeFrustum[1], &pCullInfo->vecFrustum[6], 
  1103.         &pCullInfo->vecFrustum[7], &pCullInfo->vecFrustum[5] ); // Far
  1104.     D3DXPlaneFromPoints( &pCullInfo->planeFrustum[2], &pCullInfo->vecFrustum[2], 
  1105.         &pCullInfo->vecFrustum[6], &pCullInfo->vecFrustum[4] ); // Left
  1106.     D3DXPlaneFromPoints( &pCullInfo->planeFrustum[3], &pCullInfo->vecFrustum[7], 
  1107.         &pCullInfo->vecFrustum[3], &pCullInfo->vecFrustum[5] ); // Right
  1108.     D3DXPlaneFromPoints( &pCullInfo->planeFrustum[4], &pCullInfo->vecFrustum[2], 
  1109.         &pCullInfo->vecFrustum[3], &pCullInfo->vecFrustum[6] ); // Top
  1110.     D3DXPlaneFromPoints( &pCullInfo->planeFrustum[5], &pCullInfo->vecFrustum[1], 
  1111.         &pCullInfo->vecFrustum[0], &pCullInfo->vecFrustum[4] ); // Bottom
  1112. }
  1113. //-----------------------------------------------------------------------------
  1114. // Name: RenderScene()
  1115. // Desc:
  1116. //-----------------------------------------------------------------------------
  1117. HRESULT CMyApplication::RenderScene()
  1118. {
  1119.     HRESULT hr;
  1120.     // Test the cooperative level to see if it's okay to render
  1121.     if( FAILED( hr = g_pd3dDevice->TestCooperativeLevel() ) )
  1122.     {
  1123.         // If the device was lost, do not render until we get it back
  1124.         if( D3DERR_DEVICELOST == hr )
  1125.             return S_OK;
  1126.         // Check if the device needs to be resized.
  1127.         if( D3DERR_DEVICENOTRESET == hr )
  1128.         {
  1129.             m_bDisplayReady = FALSE;
  1130.             InvalidateDeviceObjects();
  1131.             // Resize the device
  1132.             if( SUCCEEDED( g_pd3dDevice->Reset( &m_d3dpp ) ) )
  1133.             {
  1134.                 // Initialize the app's device-dependent objects
  1135.                 if( SUCCEEDED( RestoreDeviceObjects() ) )
  1136.                 {
  1137.                     m_bDisplayReady = TRUE;
  1138.                     return S_OK;
  1139.                 }
  1140.             }
  1141.             PostMessage( m_hWndMain, WM_CLOSE, 0, 0 );
  1142.         }
  1143.         return hr;
  1144.     }
  1145.     // Render the scene based on current state of the app
  1146.     switch( m_dwAppState )
  1147.     {
  1148.         case APPSTATE_LOADSPLASH:
  1149.             // Nothing to render while loading the splash screen
  1150.             break;
  1151.         case APPSTATE_DISPLAYSPLASH:
  1152.             RenderSplash();
  1153.             g_pd3dDevice->Present( 0, 0, 0, 0 );
  1154.             break;
  1155.         case APPSTATE_BEGINLEVELSCREEN:
  1156.             // Nothing to render while starting sound to advance a level
  1157.             break;
  1158.         case APPSTATE_DISPLAYLEVELSCREEN:
  1159.             DisplayLevelIntroScreen( m_dwLevel );
  1160.             g_pd3dDevice->Present( 0, 0, 0, 0 );
  1161.             break;
  1162.         case APPSTATE_ACTIVE:
  1163.         case APPSTATE_WAITFORMUSICEND:
  1164.             RenderFrame();
  1165.             g_pd3dDevice->Present( 0, 0, 0, 0 );
  1166.             break;
  1167.     }
  1168.     return S_OK;
  1169. }
  1170. //-----------------------------------------------------------------------------
  1171. // Name: RenderFrame()
  1172. // Desc:
  1173. //-----------------------------------------------------------------------------
  1174. HRESULT CMyApplication::RenderFrame()
  1175. {
  1176.     // Set the world matrix
  1177.     D3DXMATRIX matWorld;
  1178.     D3DXMatrixIdentity( &matWorld );
  1179.     g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  1180.     // Set the app view matrix for normal viewing
  1181.     D3DXMATRIX mView = m_Camera.GetViewMatrix();
  1182.     g_pd3dDevice->SetTransform( D3DTS_VIEW,       &mView );
  1183.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1184.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  1185.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  1186.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  1187.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
  1188.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1189.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1190.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU,  D3DTADDRESS_WRAP );
  1191.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP );
  1192.     g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
  1193.     g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
  1194.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  1195.     g_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE );
  1196.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      TRUE );
  1197.     g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,     TRUE );
  1198.     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, g_Profile.aThemes[m_nCurTheme].dwAmbientLight );
  1199.     m_dwNumVerts = 0;
  1200.     
  1201.     // Begin the scene
  1202.     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
  1203.     {
  1204.         // Clear the display
  1205.         g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, g_Profile.aThemes[m_nCurTheme].Sky.dwClearColor, 1.0f, 0L );
  1206.         g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  1207.         
  1208.         // Render the sky
  1209.         if( m_pSkyDome && !m_bWireMode && g_Profile.bRenderSky )
  1210.         {
  1211.             D3DXMATRIX matWorld;
  1212.             D3DXMATRIX matScale;
  1213.             D3DXMATRIX matTrans;
  1214.             D3DMATERIAL9 mtrl;
  1215.             ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
  1216.             mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
  1217.             mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
  1218.             mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
  1219.             mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
  1220.             g_pd3dDevice->SetMaterial( &mtrl );
  1221.             D3DXMatrixScaling( &matScale, g_Profile.aThemes[m_nCurTheme].Sky.fScaleX, g_Profile.aThemes[m_nCurTheme].Sky.fScaleY, g_Profile.aThemes[m_nCurTheme].Sky.fScaleZ );
  1222.             D3DXMatrixTranslation( &matTrans, m_Camera.GetEyePt().x, 
  1223.                                               m_Camera.GetEyePt().y + g_Profile.aThemes[m_nCurTheme].Sky.fOffsetY, 
  1224.                                               m_Camera.GetEyePt().z );
  1225.             D3DXMatrixMultiply( &matWorld, &matTrans, &matScale );
  1226.             g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,     FALSE );
  1227.             g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,     D3DBLEND_ONE );
  1228.             g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,    D3DBLEND_ZERO );
  1229.             g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      FALSE );
  1230.             g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
  1231.             g_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,    FALSE );
  1232.         
  1233.             m_Camera.SetProjParams( g_Profile.fFOV, 1.0f, 0.01f, 1000.0f ); 
  1234.             D3DXMATRIX mProj = m_Camera.GetProjMatrix();
  1235.             g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProj );
  1236.             g_pd3dDevice->SetTexture( 0, m_pSkyTexture );
  1237.             g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  1238.             m_pSkyDome->Render( g_pd3dDevice );
  1239.         }
  1240.         m_Camera.SetProjParams( g_Profile.fFOV, 1.0f, 0.01f, g_Profile.fZFarDist ); 
  1241.         D3DXMATRIX mProj = m_Camera.GetProjMatrix();
  1242.         g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProj );
  1243.         // Set either wireframe or SOLID
  1244.         if( m_bDebugMode && m_bWireMode )
  1245.             g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
  1246.         else
  1247.             g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  1248.         g_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,    TRUE );
  1249.         g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      TRUE );
  1250.         g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
  1251.         g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,     TRUE );
  1252.         g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  1253.         g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,  FALSE );
  1254.         g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, g_Profile.aThemes[m_nCurTheme].dwAmbientLight );
  1255.         // Draw the terrain
  1256.         if( g_pTerrain )
  1257.             g_pTerrain->RenderFrame( &m_dwNumVerts, &m_Camera );
  1258.         g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  1259.         
  1260.         if( m_p3DDrawManager )
  1261.             m_p3DDrawManager->Render();
  1262.         // Render the UI
  1263.         if( m_pViewportVB && g_Profile.bRenderUI )
  1264.         {
  1265.             g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,         FALSE );
  1266.             g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  1267.             g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_SRCALPHA );
  1268.             g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_INVSRCALPHA );
  1269.             g_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,        FALSE );
  1270.             g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          TRUE );
  1271.             g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,     TRUE );
  1272.             g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE );
  1273.             g_pd3dDevice->SetRenderState( D3DRS_ALPHAREF,         0x01 );
  1274.             g_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
  1275.             g_pd3dDevice->SetTexture( 0, m_pUITexture );
  1276.             g_pd3dDevice->SetFVF( D3DFVF_SCREENVERTEX );
  1277.             g_pd3dDevice->SetStreamSource( 0, m_pViewportVB, 0, sizeof(SCREENVERTEX) );
  1278.             g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0, 2 );
  1279.         }
  1280.         // Render the Radar
  1281.         if( m_pRadarVB && g_Profile.bRenderRadar )
  1282.         {
  1283.             g_pd3dDevice->SetTexture( 0, m_pRadarTexture );
  1284.             g_pd3dDevice->SetFVF( D3DFVF_SCREENVERTEX );
  1285.             g_pd3dDevice->SetStreamSource( 0, m_pRadarVB, 0, sizeof(SCREENVERTEX) );
  1286.             g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0, 2 );
  1287.         }
  1288.         // Render UI text
  1289.         TCHAR strBuffer[MAX_PATH];
  1290.         DWORD dwTextColor = 0xFFFFFF00;
  1291.         // Display enemy count
  1292.         if( m_pGameFont && g_pTerrain )
  1293.         {
  1294.             _stprintf( strBuffer, _T("%d"), g_pTerrain->m_dwEnemyCount );
  1295.             m_pGameFont->DrawTextScaled( 0.63f, -0.7f, 0.9f, 0.05f, 0.05f,
  1296.                                         dwTextColor, strBuffer, D3DFONT_FILTERED );
  1297.         }
  1298. /*
  1299.         // Display shield
  1300.         if( m_pGameFont && g_pTerrain )
  1301.         {
  1302.             _stprintf( strBuffer, _T("%0.0f"), m_pShip->m_fShield );
  1303.             m_pGameFont->DrawTextScaled( 0.63f, 0.0f, 0.9f, 0.05f, 0.05f,
  1304.                                         dwTextColor, strBuffer, D3DFONT_FILTERED );
  1305.         }
  1306. */
  1307.         // Render any text
  1308.         if( m_bDebugMode && g_Profile.dwRenderText > 0 )
  1309.         {
  1310.             dwTextColor = 0xFFFFFF00;
  1311.             DWORD dwNumZonesInView = 0;
  1312.             if( g_pTerrain )
  1313.                 dwNumZonesInView = g_pTerrain->m_dwNumZonesInView;
  1314.             _stprintf( strBuffer, _T("Tris=%d FPS=%.02f Zones=%d"), m_dwNumVerts, m_fFPS, dwNumZonesInView );
  1315.             m_pGameFont->DrawTextScaled( -1.0f, -1.0f, 0.9f, 0.05f, 0.05f,
  1316.                                          dwTextColor, strBuffer, D3DFONT_FILTERED );
  1317.             if( g_Profile.dwRenderText == 1 && m_pShip )
  1318.             {
  1319.                 _stprintf( strBuffer, _T("CM P=(%0.1f,%0.1f,%0.1f) V=(%0.1f,%0.1f,%0.1f) A=(%0.1f,%0.1f,%0.1f)"), 
  1320.                             m_pShip->m_pSource->m_vCMPos.x, m_pShip->m_pSource->m_vCMPos.y, m_pShip->m_pSource->m_vCMPos.z, 
  1321.                             m_pShip->m_pSource->m_vCMVel.x, m_pShip->m_pSource->m_vCMVel.y, m_pShip->m_pSource->m_vCMVel.z,
  1322.                             m_pShip->m_pSource->m_vCMAcc.x, m_pShip->m_pSource->m_vCMAcc.y, m_pShip->m_pSource->m_vCMAcc.z );
  1323.                 m_pGameFont->DrawTextScaled( -1.0f, 0.6f, 0.9f, 0.05f, 0.05f,
  1324.                                              dwTextColor, strBuffer, D3DFONT_FILTERED );
  1325.                 _stprintf( strBuffer, _T("O=(%0.1f,%0.1f,%0.1f,%0.1f) AV=(%0.1f,%0.1f,%0.1f) AA=(%0.1f,%0.1f,%0.1f)"), 
  1326.                     m_pShip->m_pSource->m_qOrientation.x, m_pShip->m_pSource->m_qOrientation.y, m_pShip->m_pSource->m_qOrientation.z, m_pShip->m_pSource->m_qOrientation.w,
  1327.                     m_pShip->m_pSource->m_vAngularVel.x, m_pShip->m_pSource->m_vAngularVel.y, m_pShip->m_pSource->m_vAngularVel.z, 
  1328.                     m_pShip->m_pSource->m_vAngularMomentum.x, m_pShip->m_pSource->m_vAngularMomentum.y, m_pShip->m_pSource->m_vAngularMomentum.z );
  1329.                 m_pGameFont->DrawTextScaled( -1.0f, 0.7f, 0.9f, 0.05f, 0.05f,
  1330.                                              dwTextColor, strBuffer, D3DFONT_FILTERED );
  1331.                 // Display Object Count
  1332.                 if( g_pTerrain )
  1333.                 {
  1334.                     _stprintf( strBuffer, _T("Objects: %03ld"), g_pTerrain->m_dwObjectCount );
  1335.                     m_pGameFont->DrawTextScaled( -1.0f, 0.9f, 0.9f, 0.05f, 0.05f,
  1336.                                                 dwTextColor, strBuffer, D3DFONT_FILTERED );
  1337.                 }
  1338.             }
  1339.         }
  1340.         // Render "Paused" text if game is paused
  1341.         if( m_bPaused && m_pGameFont && !m_bDebugMode )
  1342.         {
  1343.             DarkenScene( 0.5f );
  1344.             g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  1345.             g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  1346.             m_pGameFont->DrawTextScaled( -0.3f, 0.0f, 0.9f, 0.10f, 0.10f, 0xffffffff, _T("Paused"), D3DFONT_FILTERED|D3DFONT_CENTERED_X|D3DFONT_CENTERED_Y );
  1347.         }
  1348. //        if( m_pShip->fShowDelay > 0.0f )
  1349. //            DarkenScene( m_pShip->fShowDelay/2.0f );
  1350.         // Render game menu
  1351.         if( m_pCurrentMenu )
  1352.         {
  1353.             DarkenScene( 0.5f );
  1354.             m_pCurrentMenu->Render( m_pMenuFont );
  1355.         }
  1356.         g_pd3dDevice->EndScene();
  1357.     }
  1358.     static FLOAT fLastTime = 0.0f;
  1359.     static DWORD dwFrames  = 0L;
  1360.     FLOAT fTime = DXUtil_Timer( TIMER_GETABSOLUTETIME );
  1361.     ++dwFrames;
  1362.     // Update the scene stats once per second
  1363.     if( fTime - fLastTime > 1.0f )
  1364.     {
  1365.         m_fFPS    = dwFrames / (fTime - fLastTime);
  1366.         fLastTime = fTime;
  1367.         dwFrames  = 0L;
  1368.     }
  1369.     return S_OK;
  1370. }
  1371. //-----------------------------------------------------------------------------
  1372. // Name: InvalidateDeviceObjects()
  1373. // Desc:
  1374. //-----------------------------------------------------------------------------
  1375. HRESULT CMyApplication::InvalidateDeviceObjects()
  1376. {
  1377.     if( m_p3DDrawManager )
  1378.         m_p3DDrawManager->InvalidateDeviceObjects();
  1379.     if( m_pSkyDome )
  1380.         m_pSkyDome->InvalidateDeviceObjects();
  1381.     if( g_pTerrain )
  1382.         g_pTerrain->InvalidateDeviceObjects();
  1383.     if( m_pGameFont )
  1384.         m_pGameFont->InvalidateDeviceObjects();
  1385.     if( m_pMenuFont )
  1386.         m_pMenuFont->InvalidateDeviceObjects();
  1387.     // Invalidate the enemy models
  1388.     for( int iEnemy=0; iEnemy<g_Profile.nNumEnemies; iEnemy++ )
  1389.     {
  1390.         C3DModel* pModel = g_Profile.aEnemyStyles[iEnemy].pModel;
  1391.         if( pModel )
  1392.             pModel->InvalidateDeviceObjects();
  1393.     }
  1394.     C3DModel* pModel = g_Profile.Blaster.pModel;
  1395.     if( pModel )
  1396.         pModel->InvalidateDeviceObjects();
  1397.     SAFE_RELEASE( m_pRadarTexture );
  1398.     SAFE_RELEASE( m_pTempRadarTexture );
  1399.     return S_OK;
  1400. }
  1401. //-----------------------------------------------------------------------------
  1402. // Name: DeleteDeviceObjects()
  1403. // Desc:
  1404. //-----------------------------------------------------------------------------
  1405. HRESULT CMyApplication::DeleteDeviceObjects()
  1406. {
  1407.     if( m_p3DDrawManager )
  1408.         m_p3DDrawManager->DeleteDeviceObjects();
  1409.     SAFE_RELEASE( g_Profile.Blaster.pParticleTexture );
  1410.     SAFE_RELEASE( m_pSkyTexture );
  1411.     SAFE_RELEASE( m_pUITexture );
  1412.     SAFE_RELEASE( m_pSplashTexture );
  1413.     SAFE_DELETE( m_pGameFont );
  1414.     SAFE_DELETE( m_pMenuFont );
  1415.     if( g_pTerrain != NULL )
  1416.     {
  1417.         g_pTerrain->InvalidateDeviceObjects();
  1418.         g_pTerrain->DeleteDeviceObjects();
  1419.         g_pTerrain->FinalCleanup();
  1420.         m_pShip = NULL;
  1421.         if( m_pShipModel )
  1422.             m_pShipModel->DeleteDeviceObjects();
  1423.         SAFE_DELETE( m_pShipModel );
  1424.     }
  1425.     SAFE_DELETE( g_pTerrain );
  1426.     SAFE_DELETE( m_pSkyDome );
  1427.     SAFE_RELEASE( m_pViewportVB );
  1428.     SAFE_RELEASE( m_pRadarVB );
  1429.     for( int iEnemy=0; iEnemy<g_Profile.nNumEnemies; iEnemy++ )
  1430.     {
  1431.         C3DModel* pModel = g_Profile.aEnemyStyles[iEnemy].pModel;
  1432.         if( pModel )
  1433.             pModel->DeleteDeviceObjects();
  1434.         SAFE_DELETE( g_Profile.aEnemyStyles[iEnemy].pModel );
  1435.     }
  1436.     C3DModel* pModel = g_Profile.Blaster.pModel;
  1437.     if( pModel )
  1438.     {
  1439.         pModel->DeleteDeviceObjects();
  1440.         SAFE_DELETE( g_Profile.Blaster.pModel );
  1441.     }
  1442.     SAFE_RELEASE( g_pd3dDevice );
  1443.     return S_OK;
  1444. }
  1445. //-----------------------------------------------------------------------------
  1446. // Name: FinalCleanup()
  1447. // Desc: Cleanup everything
  1448. //-----------------------------------------------------------------------------
  1449. VOID CMyApplication::FinalCleanup()
  1450. {
  1451.     InvalidateDeviceObjects();
  1452.     DeleteDeviceObjects();
  1453.     DestroySoundObjects();
  1454.     SAFE_DELETE( m_pInputManager );
  1455.     SAFE_DELETE( m_p3DDrawManager );
  1456.     DestroyMenus();
  1457.     if( m_pFileWatch )
  1458.     {
  1459.         m_pFileWatch->Cleanup();
  1460.         SAFE_DELETE( m_pFileWatch );
  1461.     }
  1462. }
  1463. //-----------------------------------------------------------------------------
  1464. // Name: AdvanceLevel()
  1465. // Desc:
  1466. //-----------------------------------------------------------------------------
  1467. VOID CMyApplication::AdvanceLevel()
  1468. {
  1469.     // Up the level
  1470.     m_dwLevel++;
  1471.     srand( timeGetTime() );
  1472.     // Clear any stray objects (anything but the ship) out of the display list
  1473.     if( g_pTerrain )
  1474.         g_pTerrain->ClearStrayObjects();
  1475.     // Reset ship position
  1476.     if( m_pShip )
  1477.     {
  1478.         D3DXVECTOR3 vPos;
  1479.         vPos.x = rnd(0.0f,1.0f)*ZONE_WIDTH*g_pTerrain->m_dwWorldWidth;
  1480.         vPos.z = rnd(0.0f,1.0f)*ZONE_HEIGHT*g_pTerrain->m_dwWorldHeight;   
  1481.         vPos.y = g_pTerrain->GetHeight( vPos.x, vPos.z ) + 10.0f;
  1482.         m_pShip->m_pSource->m_vCMPos      = vPos;
  1483.         m_pShip->m_pSource->m_vAngularVel = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  1484.         m_pShip->m_pSource->m_vCMVel      = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  1485.         m_pShip->m_vEulerAngles           = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
  1486.     }
  1487.     // Create donuts for the new level
  1488.     for( WORD i=0; i<(g_Profile.nNumEnemiesPerLevelScale*m_dwLevel+g_Profile.nNumEnemiesBase); i++ )
  1489.     {
  1490.         DWORD dwEnemyStyle;
  1491.         if( g_Profile.bForceEnemySelect )
  1492.             dwEnemyStyle = g_Profile.nSelectEnemy;
  1493.         else
  1494.             dwEnemyStyle = rand() % g_Profile.nNumEnemies;
  1495.         CreateEnemy( dwEnemyStyle, NULL, rnd(-D3DX_PI,D3DX_PI) );
  1496.     }
  1497. }
  1498. //-----------------------------------------------------------------------------
  1499. // Name: DarkenScene()
  1500. // Desc:
  1501. //-----------------------------------------------------------------------------
  1502. VOID CMyApplication::DarkenScene( FLOAT fAmount )
  1503. {
  1504.     if( g_pd3dDevice==NULL )
  1505.         return;
  1506.     // Setup a dark square to cover the scene
  1507.     DWORD dwAlpha = (fAmount<1.0f) ? ((DWORD)(255*fAmount))<<24L : 0xff000000;
  1508.     SCREENVERTEX* v;
  1509.     m_pViewportVB->Lock( 0, 0, (void**)&v, 0 );
  1510.     v[0].color = v[1].color = v[2].color = v[3].color = dwAlpha;
  1511.     m_pViewportVB->Unlock();
  1512.     // Set renderstates
  1513.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  1514.     g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  1515.     g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  1516.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,   FALSE );
  1517.     g_pd3dDevice->SetTexture( 0, NULL );
  1518.     // Draw a big, gray square
  1519.     g_pd3dDevice->SetFVF( D3DFVF_SCREENVERTEX );
  1520.     g_pd3dDevice->SetStreamSource( 0, m_pViewportVB, 0, sizeof(SCREENVERTEX) );
  1521.     g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0, 2 );
  1522.     // Restore states
  1523.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1524.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  1525.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  1526.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  1527.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
  1528.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
  1529.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU,  D3DTADDRESS_CLAMP );
  1530.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV,  D3DTADDRESS_CLAMP );
  1531. }
  1532. //-----------------------------------------------------------------------------
  1533. // Name: DisplayLevelIntroScreen()
  1534. // Desc:
  1535. //-----------------------------------------------------------------------------
  1536. VOID CMyApplication::DisplayLevelIntroScreen( DWORD dwLevel )
  1537. {
  1538.     if( g_pd3dDevice==NULL )
  1539.         return;
  1540.     // Begin the scene
  1541.     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
  1542.     {
  1543.         // Erase the screen
  1544.         g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0L );
  1545.         g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  1546.         g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  1547.         TCHAR strLevel[80];
  1548.         _stprintf( strLevel, _T("Level %ld"), dwLevel );
  1549.         m_pGameFont->DrawTextScaled( -0.3f, 0.0f, 0.9f, 0.10f, 0.10f, 0xffffffff, strLevel, D3DFONT_FILTERED|D3DFONT_CENTERED_X|D3DFONT_CENTERED_Y );
  1550.         DarkenScene( 1.0f - sinf(D3DX_PI*DXUtil_Timer( TIMER_GETAPPTIME )/3.0f) );
  1551.         // End the scene
  1552.         g_pd3dDevice->EndScene();
  1553.     }
  1554. }
  1555. //-----------------------------------------------------------------------------
  1556. // Name: RenderSplash()
  1557. // Desc:
  1558. //-----------------------------------------------------------------------------
  1559. VOID CMyApplication::RenderSplash()
  1560. {
  1561.     // Set the world matrix
  1562.     D3DXMATRIX matWorld;
  1563.     D3DXMatrixIdentity( &matWorld );
  1564.     g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  1565.     // Set the app view matrix for normal viewing
  1566.     D3DXMATRIX mView = m_Camera.GetViewMatrix();
  1567.     g_pd3dDevice->SetTransform( D3DTS_VIEW,       &mView );
  1568.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  1569.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  1570.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  1571.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  1572.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
  1573.     g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_DISABLE );
  1574.     g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE );
  1575.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  1576.     g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  1577.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  1578.     g_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE );
  1579.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,      TRUE );
  1580.     g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,     TRUE );
  1581.     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, g_Profile.aThemes[m_nCurTheme].dwAmbientLight );
  1582.     m_dwNumVerts = 0;
  1583.     
  1584.     // Begin the scene
  1585.     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
  1586.     {
  1587.         // Clear the display
  1588.         g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, g_Profile.aThemes[m_nCurTheme].Sky.dwClearColor, 1.0f, 0L );
  1589.        
  1590.         // Render the UI
  1591.         g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  1592.         g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,         FALSE );
  1593.         g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  1594.         g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,         D3DBLEND_SRCALPHA );
  1595.         g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,        D3DBLEND_INVSRCALPHA );
  1596.         g_pd3dDevice->SetRenderState( D3DRS_FOGENABLE,        FALSE );
  1597.         g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          TRUE );
  1598.         g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,     TRUE );
  1599.         g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE,  TRUE );
  1600.         g_pd3dDevice->SetRenderState( D3DRS_ALPHAREF,         0x01 );
  1601.         g_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
  1602.         g_pd3dDevice->SetTexture( 0, m_pSplashTexture );
  1603.         g_pd3dDevice->SetFVF( D3DFVF_SCREENVERTEX );
  1604.         g_pd3dDevice->SetStreamSource( 0, m_pViewportVB, 0, sizeof(SCREENVERTEX) );
  1605.         g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0, 2 );
  1606.         g_pd3dDevice->EndScene();
  1607.     }
  1608.     static FLOAT fLastTime = 0.0f;
  1609.     static DWORD dwFrames  = 0L;
  1610.     FLOAT fTime = DXUtil_Timer( TIMER_GETABSOLUTETIME );
  1611.     ++dwFrames;
  1612.     // Update the scene stats once per second
  1613.     if( fTime - fLastTime > 1.0f )
  1614.     {
  1615.         m_fFPS    = dwFrames / (fTime - fLastTime);
  1616.         fLastTime = fTime;
  1617.         dwFrames  = 0L;
  1618.     }
  1619. }
  1620. //-----------------------------------------------------------------------------
  1621. // Name:
  1622. // Desc:
  1623. //-----------------------------------------------------------------------------
  1624. VOID CMyApplication::ConstructMenus()
  1625. {
  1626.     // Build video sub menu
  1627.     CMenuItem* pVideoSubMenu = new CMenuItem( _T("Video Menu"), MENU_VIDEO );
  1628.     if( NULL == pVideoSubMenu )
  1629.         return;
  1630.     pVideoSubMenu->Add( new CMenuItem( _T("Windowed"), MENU_WINDOWED ) );
  1631.     pVideoSubMenu->Add( new CMenuItem( _T("640x480"),  MENU_640x480 ) );
  1632.     pVideoSubMenu->Add( new CMenuItem( _T("800x600"),  MENU_800x600 ) );
  1633.     pVideoSubMenu->Add( new CMenuItem( _T("1024x768"), MENU_1024x768 ) );
  1634.     pVideoSubMenu->Add( new CMenuItem( _T("Back"),     MENU_BACK ) );
  1635.     // Build sound menu
  1636.     CMenuItem* pSoundSubMenu = new CMenuItem( _T("Sound Menu"), MENU_SOUND );
  1637.     if( NULL == pSoundSubMenu )
  1638.         return;
  1639.     pSoundSubMenu->Add( new CMenuItem( _T("Sound On"),  MENU_SOUNDON ) );
  1640.     pSoundSubMenu->Add( new CMenuItem( _T("Sound Off"), MENU_SOUNDOFF ) );
  1641.     pSoundSubMenu->Add( new CMenuItem( _T("Back"),      MENU_BACK ) );
  1642.     // Build input menu
  1643.     CMenuItem* pInputSubMenu = new CMenuItem( _T("Input Menu"), MENU_INPUT );
  1644.     if( NULL == pInputSubMenu )
  1645.         return;
  1646.     pInputSubMenu->Add( new CMenuItem( _T("View Devices"),   MENU_VIEWDEVICES ) );
  1647.     pInputSubMenu->Add( new CMenuItem( _T("Config Devices"), MENU_CONFIGDEVICES ) );
  1648.     pInputSubMenu->Add( new CMenuItem( _T("Back"),           MENU_BACK ) );
  1649.     // Build main menu
  1650.     m_pMainMenu = new CMenuItem( _T("Main Menu"),  MENU_MAIN );
  1651.     if( NULL == m_pMainMenu )
  1652.         return;
  1653.     m_pMainMenu->Add( new CMenuItem( _T("Resume"), MENU_BACK ) );
  1654.     m_pMainMenu->Add( pVideoSubMenu );
  1655.     m_pMainMenu->Add( pSoundSubMenu );
  1656.     m_pMainMenu->Add( pInputSubMenu );
  1657.     m_pMainMenu->Add( new CMenuItem( _T("Quit"), MENU_QUIT ) );
  1658.     return;
  1659. }
  1660. //-----------------------------------------------------------------------------
  1661. // Name:
  1662. // Desc:
  1663. //-----------------------------------------------------------------------------
  1664. VOID CMyApplication::DestroyMenus()
  1665. {
  1666.     SAFE_DELETE( m_pQuitMenu );
  1667.     SAFE_DELETE( m_pMainMenu );
  1668. }
  1669. //-----------------------------------------------------------------------------
  1670. // Name: UpdateMenus()
  1671. // Desc:
  1672. //-----------------------------------------------------------------------------
  1673. VOID CMyApplication::UpdateMenus()
  1674. {
  1675.     if( m_pCurrentMenu == NULL )
  1676.         return;
  1677.     CInputManager::UserInput* pUserInput = NULL;
  1678.     pUserInput = m_pInputManager->GetUserInput();
  1679.     // Keep track of current selected menu, to check later for changes
  1680.     //DWORD dwCurrentSelectedMenu = m_pCurrentMenu->dwSelectedMenu;
  1681.     // Check for menu up/down input
  1682.     if( pUserInput->bDoMenuUp )
  1683.     {
  1684.         pUserInput->bDoMenuUp = FALSE;
  1685.         if( m_pCurrentMenu->dwSelectedMenu > 0 )
  1686.             m_pCurrentMenu->dwSelectedMenu--;
  1687.         else
  1688.             m_pCurrentMenu->dwSelectedMenu = m_pCurrentMenu->dwNumChildren - 1;
  1689.     }
  1690.     else if( pUserInput->bDoMenuDown )
  1691.     {
  1692.         pUserInput->bDoMenuDown = FALSE;
  1693.         if( (m_pCurrentMenu->dwSelectedMenu+1) < m_pCurrentMenu->dwNumChildren )
  1694.             m_pCurrentMenu->dwSelectedMenu++;
  1695.         else
  1696.             m_pCurrentMenu->dwSelectedMenu = 0;
  1697.     }
  1698.     // The the current menu changed, play a sound
  1699. //    if( dwCurrentSelectedMenu != m_pCurrentMenu->dwSelectedMenu )
  1700. //        PlaySoundEffect( m_pExplosionSphereSound, &g_Profile.ExplosionSphere);
  1701.     if( pUserInput->bDoMenuSelect )
  1702.     {
  1703.         pUserInput->bDoMenuSelect = FALSE;
  1704. //        PlaySoundEffect( m_pExplosionSphereSound, &g_Profile.ExplosionSphere);
  1705.         DWORD dwID = m_pCurrentMenu->pChild[m_pCurrentMenu->dwSelectedMenu]->dwID;
  1706.         switch( dwID )
  1707.         {
  1708.             case MENU_BACK:
  1709.                 m_pCurrentMenu = m_pCurrentMenu->pParent;
  1710.                 break;
  1711.             case MENU_VIDEO:
  1712.             case MENU_SOUND:
  1713.             case MENU_INPUT:
  1714.                 m_pCurrentMenu = m_pCurrentMenu->pChild[m_pCurrentMenu->dwSelectedMenu];
  1715.                 break;
  1716.             case MENU_WINDOWED:
  1717.                 SwitchDisplayModes( FALSE, 0L, 0L );
  1718.                 m_pCurrentMenu = NULL;
  1719.                 break;
  1720.             case MENU_640x480:
  1721.                 SwitchDisplayModes( TRUE, 640, 480 );
  1722.                 m_pCurrentMenu = NULL;
  1723.                 break;
  1724.             case MENU_800x600:
  1725.                 SwitchDisplayModes( TRUE, 800, 600 );
  1726.                 m_pCurrentMenu = NULL;
  1727.                 break;
  1728.             case MENU_1024x768:
  1729.                 SwitchDisplayModes( TRUE, 1024, 768 );
  1730.                 m_pCurrentMenu = NULL;
  1731.                 break;
  1732.             case MENU_SOUNDON:
  1733.                 if( m_pMusicManager == NULL )
  1734.                     CreateSoundObjects( m_hWndMain );
  1735.                 m_pCurrentMenu = NULL;
  1736.                 break;
  1737.             case MENU_SOUNDOFF:
  1738.                 if( m_pMusicManager )
  1739.                     DestroySoundObjects();
  1740.                 m_pCurrentMenu = NULL;
  1741.                 break;
  1742.             case MENU_VIEWDEVICES:
  1743.             {
  1744.                 m_bMouseVisible = TRUE;
  1745.                 DXUtil_Timer( TIMER_STOP );
  1746.                 if( m_pInputManager )
  1747.                     m_pInputManager->ViewDevices();
  1748.                 m_bMouseVisible = FALSE;
  1749.                 DXUtil_Timer( TIMER_START );
  1750.                 m_pCurrentMenu = NULL;
  1751.                 break;
  1752.             }
  1753.             case MENU_CONFIGDEVICES:
  1754.             {
  1755.                 m_bMouseVisible = TRUE;
  1756.                 DXUtil_Timer( TIMER_STOP );
  1757.                 if( m_pInputManager )
  1758.                     m_pInputManager->ConfigDevices();
  1759.                 DXUtil_Timer( TIMER_START );
  1760.                 m_bMouseVisible = FALSE;
  1761.                 m_pCurrentMenu = NULL;
  1762.                 break;
  1763.             }
  1764.             case MENU_QUIT:
  1765.                 PostMessage( m_hWndMain, WM_CLOSE, 0, 0 );
  1766.                 m_pCurrentMenu = NULL;
  1767.                 break;
  1768.         }
  1769.     }
  1770.     // Check if the menu system is being exitted
  1771.     if( pUserInput->bDoMenuQuit )
  1772.     {
  1773.         pUserInput->bDoMenuQuit = FALSE;
  1774.         m_pCurrentMenu = NULL;
  1775.     }
  1776.     // If the menu is going away, go back to game play actions
  1777. //    if( m_pCurrentMenu == NULL )
  1778. //        m_pInputDeviceManager->SetActionFormat( m_diafGame, FALSE );
  1779. }
  1780. //-----------------------------------------------------------------------------
  1781. // Display support code (using Direct3D functionality from D3DUtil.h)
  1782. //-----------------------------------------------------------------------------
  1783. //-----------------------------------------------------------------------------
  1784. // Name: ReloadWorld()
  1785. // Desc:
  1786. //-----------------------------------------------------------------------------
  1787. HRESULT CMyApplication::ReloadWorld()
  1788. {
  1789.     InvalidateDeviceObjects();
  1790.     DeleteDeviceObjects();
  1791.     FinalCleanup();
  1792.     g_Profile.GetProfile( m_strProfilePath );
  1793.     OneTimeSceneInit( m_hWndMain );
  1794.     return S_OK;
  1795. }
  1796. //-----------------------------------------------------------------------------
  1797. // Name: SwitchDisplayModes()
  1798. // Desc:
  1799. //-----------------------------------------------------------------------------
  1800. HRESULT CMyApplication::SwitchDisplayModes( BOOL bFullScreen, DWORD dwWidth, DWORD dwHeight )
  1801. {
  1802.     HRESULT hr;
  1803.     if( FALSE==m_bIsActive || FALSE==m_bDisplayReady )
  1804.         return S_OK;
  1805.     // Check to see if a change was actually requested
  1806.     if( bFullScreen )
  1807.     {
  1808.         if( m_dwScreenWidth==dwWidth && m_dwScreenHeight==dwHeight &&
  1809.             m_bFullScreen==bFullScreen )
  1810.             return S_OK;
  1811.     }
  1812.     else
  1813.     {
  1814. //        if( m_bFullScreen == FALSE )
  1815. //            return S_OK;
  1816.     }
  1817.     
  1818.     // Invalidate the old display objects
  1819.     m_bDisplayReady = FALSE;
  1820.     InvalidateDeviceObjects();
  1821.     if( bFullScreen )
  1822.     {
  1823.         // Set windowed-mode style
  1824.         SetWindowLong( m_hWndMain, GWL_STYLE, m_dwWindowStyle|WS_VISIBLE );
  1825.     }
  1826.     else
  1827.     {
  1828.         // Set fullscreen-mode style
  1829.         SetWindowLong( m_hWndMain, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
  1830.     }
  1831.     
  1832.     // Set up the new presentation paramters
  1833.     if( bFullScreen )
  1834.     {
  1835.         m_d3dpp.Windowed         = FALSE;
  1836.         m_d3dpp.hDeviceWindow    = m_hWndMain;
  1837.         m_d3dpp.BackBufferWidth  = m_dwScreenWidth  = dwWidth;
  1838.         m_d3dpp.BackBufferHeight = m_dwScreenHeight = dwHeight;
  1839.         m_d3dpp.BackBufferFormat = m_d3dfmtFullscreen;
  1840.     }
  1841.     else
  1842.     {
  1843.         m_d3dpp.Windowed         = TRUE;
  1844.         m_d3dpp.hDeviceWindow    = NULL;
  1845.         m_d3dpp.BackBufferWidth  = 0L;
  1846.         m_d3dpp.BackBufferHeight = 0L;
  1847.         m_d3dpp.BackBufferFormat = m_DesktopMode.Format;
  1848.     }
  1849.     // Reset the device
  1850.     if( SUCCEEDED( hr = g_pd3dDevice->Reset( &m_d3dpp ) ) )
  1851.     {
  1852.         m_bFullScreen   = bFullScreen;
  1853.         if( SUCCEEDED( hr = RestoreDeviceObjects() ) )
  1854.         {
  1855.             m_bDisplayReady = TRUE;
  1856.             return S_OK;
  1857.         }
  1858.     }
  1859.     // If we get here, a fatal error occurred
  1860.     PostMessage( m_hWndMain, WM_CLOSE, 0, 0 );
  1861.     return E_FAIL;
  1862. }
  1863. //-----------------------------------------------------------------------------
  1864. // Sound support code (using DMusic functionality from DMUtil.h)
  1865. //-----------------------------------------------------------------------------
  1866. //-----------------------------------------------------------------------------
  1867. // Name: CreateSoundObjects()
  1868. // Desc:
  1869. //-----------------------------------------------------------------------------
  1870. HRESULT CMyApplication::CreateSoundObjects( HWND hWnd )
  1871. {
  1872.     HRESULT hr;
  1873.     // Create the music manager class, used to create the sounds
  1874.     m_pMusicManager = new CMusicManager();
  1875.     if( NULL == m_pMusicManager )
  1876.         return DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY );
  1877.     if( FAILED( hr = m_pMusicManager->Initialize( hWnd, 128, DMUS_APATH_DYNAMIC_STEREO, NULL ) ) )
  1878.         return DXTRACE_ERR( TEXT("m_pMusicManager->Initialize"), hr );
  1879.     // Instruct the music manager where to find the files
  1880.     TCHAR strSearchPath[MAX_PATH];
  1881.     lstrcpyn( strSearchPath, m_strCurrentWorkingDir, MAX_PATH-10 );
  1882.     lstrcat( strSearchPath, TEXT("\audio") );
  1883.     m_pMusicManager->SetSearchDirectory( strSearchPath );
  1884.     // Set up scripting
  1885.     if( FAILED( hr = m_pMusicManager->CreateScriptFromFile( &m_pMusicScript, g_Profile.szAudioScript ) ) )
  1886.         return DXTRACE_ERR( TEXT("m_pMusicManager->CreateScriptFromFile"), hr );
  1887.     // Just in case there's anything that needs to be initialized in the script.
  1888.     if( FAILED( hr = m_pMusicScript->CallRoutine( "Init" ) ) )
  1889.         return DXTRACE_ERR( TEXT("m_pMusicScript->CallRoutine"), hr );
  1890.     // One thing the script does in Init is create an audiopath for the engine.
  1891.     // We need to retrieve it so we can access the buffer and call SetFrequency in response to 
  1892.     // speed changes.
  1893.     if( m_pMusicScript )
  1894.         m_pMusicScript->GetVariableObject( "EnginePath", IID_IDirectMusicAudioPath, (void **) &m_pEnginePath );
  1895.     // For lyric notifications, we need to insert a CNotifyTool in the performance graph. This ensures
  1896.     // that it receives lyrics generated by any segment on any audiopath.
  1897.     IDirectMusicAudioPath *pPath;
  1898.     if (SUCCEEDED(m_pMusicManager->GetPerformance()->GetDefaultAudioPath( &pPath ) ) )
  1899.     {
  1900.         IDirectMusicGraph *pGraph;
  1901.         if (SUCCEEDED(pPath->GetObjectInPath( 0, DMUS_PATH_PERFORMANCE_GRAPH, 0, 
  1902.                     CLSID_DirectMusicGraph, 0, IID_IDirectMusicGraph, (void **)&pGraph ) ) )
  1903.         {
  1904.             CNotifyTool *pTool = new CNotifyTool( this );
  1905.             if (pTool)
  1906.             {
  1907.                 pGraph->InsertTool((IDirectMusicTool*) pTool,NULL,0,0); 
  1908.                 pTool->Release();
  1909.             }
  1910.             pGraph->Release();
  1911.         }
  1912.     }
  1913.     // Create the audiopaths. These will be used to manage sound for the flying objects.
  1914.     for (DWORD dwX = 0; dwX < MAX_AUDIOPATHS; dwX++)
  1915.         m_pMusicManager->GetPerformance()->CreateStandardAudioPath( DMUS_APATH_DYNAMIC_3D, 16, 
  1916.                                                                     FALSE, &m_AudioPath[dwX].m_pPath );
  1917.     UpdateFarthestAudioPath();
  1918.     // Create the Sounds    
  1919.     m_pMusicManager->CreateSegmentFromFile( &m_pBullet1Sound, g_Profile.Blaster.szFile, TRUE, FALSE ); 
  1920.     m_pMusicManager->CreateSegmentFromFile( &m_pExplosionDonutSound, g_Profile.ExplosionDonut.szFile, TRUE, FALSE ); 
  1921.     m_p3DListener = m_pMusicManager->GetListener();
  1922.     m_pMusicManager->Set3DParameters( g_Profile.flDistanceFactor, g_Profile.flDopplerFactor, g_Profile.flRolloffFactor );
  1923.     return S_OK;
  1924. }
  1925. //-----------------------------------------------------------------------------
  1926. // Name: DestroySoundObjects()
  1927. // Desc:
  1928. //-----------------------------------------------------------------------------
  1929. VOID CMyApplication::DestroySoundObjects()
  1930. {
  1931.     SAFE_DELETE( m_pMusicScript );
  1932.     for (DWORD dwI = 0; dwI < MAX_AUDIOPATHS; dwI++)  
  1933.         SAFE_RELEASE(m_AudioPath[dwI].m_pPath); 
  1934.     SAFE_RELEASE( m_pEnginePath );
  1935.     SAFE_DELETE( m_pBullet1Sound );
  1936.     SAFE_DELETE( m_pExplosionDonutSound );
  1937.     SAFE_DELETE( m_pMusicManager );
  1938.     m_p3DListener = NULL;
  1939. }
  1940. //-----------------------------------------------------------------------------
  1941. // Input support code (using DInput functionality from DIUtil.h)
  1942. //-----------------------------------------------------------------------------
  1943. //-----------------------------------------------------------------------------
  1944. // Error handling
  1945. //-----------------------------------------------------------------------------
  1946. //-----------------------------------------------------------------------------
  1947. // Name: CleanupAndDisplayError()
  1948. // Desc:
  1949. //-----------------------------------------------------------------------------
  1950. VOID CMyApplication::CleanupAndDisplayError( DWORD dwError, TCHAR* strArg1, TCHAR* strArg2 )
  1951. {
  1952.     TCHAR* strDbgOut = NULL;
  1953.     TCHAR* strMsgBox = NULL;
  1954.     // Cleanup the app
  1955.     InvalidateDeviceObjects();
  1956.     DeleteDeviceObjects();
  1957.     FinalCleanup();
  1958.     // Make the cursor visible
  1959.     SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  1960.     m_bMouseVisible = TRUE;
  1961.     // Get the appropriate error strings
  1962.     switch( dwError )
  1963.     {
  1964.         case DONUTSERR_NODIRECT3D:
  1965.             strDbgOut = _T("Could not create Direct3Dn");
  1966.             strMsgBox = _T("Could not create Direct3D.nn")
  1967.                         _T("Please make sure you have the latest DirectXn")
  1968.                         _T(".dlls installed on your system.");
  1969.             break;
  1970.         case DONUTSERR_NOD3DDEVICE:
  1971.             strDbgOut = _T("Could not create a Direct3D devicen");
  1972.             strMsgBox = _T("Could not create a Direct3D device. Yourn")
  1973.                         _T("graphics accelerator is not sufficient ton")
  1974.                         _T("run this demo, or your desktop is usingn")
  1975.                         _T("a color format that cannot be accelerated byn")
  1976.                         _T("your graphics card (try 16-bit mode).");
  1977.             break;
  1978.         case DONUTSERR_ARTLOADFAILED:            
  1979.             strDbgOut = _T("Could not load game artn");
  1980.             strMsgBox = _T("Couldn't load game art %s in %s. ")
  1981.                         _T("Either your graphics hardware does not have ")
  1982.                         _T("sufficient resources, or the DirectX SDK was ")
  1983.                         _T("not properly installed.");
  1984.             break;
  1985.         case DONUTSERR_NOINPUT:
  1986.             strDbgOut = _T("Could not create input objectsn");
  1987.             strMsgBox = _T("Could not create input objects.");
  1988.             break;
  1989.     }
  1990.     // Output the error strings
  1991.     if( strDbgOut && strMsgBox )
  1992.     {
  1993.         OutputDebugString( strDbgOut );
  1994.         TCHAR strMsg[512];
  1995.         _sntprintf( strMsg, 512, strMsgBox, strArg1, strArg2 );
  1996.         strMsg[511]=0;
  1997.         MessageBox( m_hWndMain, strMsg, m_strAppName, MB_OK );
  1998.     }
  1999. }
  2000. //-----------------------------------------------------------------------------
  2001. // Name: CreateEnemy()
  2002. // Desc:
  2003. //-----------------------------------------------------------------------------
  2004. VOID CMyApplication::CreateEnemy( DWORD dwEnemyStyle, D3DXVECTOR3* pvPosition, float fRotateY )
  2005. {
  2006.     D3DVECTOR vPosition; 
  2007.     if( !g_pTerrain )
  2008.         return;
  2009.     CEnemyStyle* pEnemyStyle = &g_Profile.aEnemyStyles[ dwEnemyStyle ];
  2010.     if( pvPosition )
  2011.     {
  2012.         vPosition = *pvPosition;
  2013.     }
  2014.     else
  2015.     {
  2016.         vPosition = D3DXVECTOR3( rnd(0.0f,1.0f)* (g_pTerrain->m_dwWorldWidth  * ZONE_WIDTH), 
  2017.                                  10.0f, 
  2018.                                  rnd(0.0f,1.0f)* (g_pTerrain->m_dwWorldHeight * ZONE_HEIGHT) );
  2019.         vPosition.y += g_pTerrain->GetHeight( vPosition.x, vPosition.z );
  2020.     }
  2021.     CEnemyShip* pEnemy = new CEnemyShip();
  2022.     if( NULL == pEnemy )
  2023.         return;
  2024.     if( g_pDebugFirstEnemy == NULL )
  2025.         g_pDebugFirstEnemy = pEnemy;
  2026.     D3DXMATRIX mOrientation;
  2027.     D3DXMatrixRotationY( &mOrientation, fRotateY );
  2028.     pEnemy->OneTimeSceneInit( 0, vPosition, &mOrientation, pEnemyStyle->pModel );
  2029.     pEnemy->InitDeviceObjects( );
  2030.     pEnemy->RestoreDeviceObjects();
  2031.     g_pTerrain->AddDisplayObject( pEnemy );
  2032. }
  2033. //-----------------------------------------------------------------------------
  2034. // Name: RenderRadarTexture()
  2035. // Desc:
  2036. //-----------------------------------------------------------------------------
  2037. HRESULT CMyApplication::RenderRadarTexture()
  2038. {
  2039.    if( NULL == g_pTerrain )
  2040.         return S_OK;
  2041.     return g_pTerrain->RenderRadar( m_pRadarTexture, m_pTempRadarTexture );
  2042. }
  2043. //-----------------------------------------------------------------------------
  2044. // Name: FindMediaFileCch()
  2045. // Desc: Look for media in based on common places with the exe will be
  2046. //-----------------------------------------------------------------------------
  2047. HRESULT CMyApplication::FindMediaFileCch( TCHAR* strPath, const long cchPath, const TCHAR* strFile )
  2048. {
  2049.     TCHAR strDestPath[MAX_PATH];
  2050.     long cchDestPath;
  2051.     TCHAR* strShortNameTmp;
  2052.     HANDLE file;
  2053.     // Try ..Donuts4media   
  2054.     lstrcpyn(strDestPath, TEXT("..\Donuts4\media\"), MAX_PATH);
  2055.     if( lstrlen(strDestPath) + lstrlen(strFile) < cchPath )
  2056.         lstrcat(strDestPath, strFile);
  2057.     cchDestPath = GetFullPathName(strDestPath, cchPath, strPath, &strShortNameTmp);
  2058.     file = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  2059.                        OPEN_EXISTING, 0, NULL );
  2060.     if( INVALID_HANDLE_VALUE != file )
  2061.     {
  2062.         CloseHandle( file );
  2063.         return S_OK;
  2064.     }
  2065.     // Try current working dir
  2066.     lstrcpyn(strDestPath, TEXT(".\"), MAX_PATH);
  2067.     if( lstrlen(strDestPath) + lstrlen(strFile) < cchPath )
  2068.         lstrcat(strDestPath, strFile);
  2069.     cchDestPath = GetFullPathName(strDestPath, cchPath, strPath, &strShortNameTmp);
  2070.     file = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  2071.                        OPEN_EXISTING, 0, NULL );
  2072.     if( INVALID_HANDLE_VALUE != file )
  2073.     {
  2074.         CloseHandle( file );
  2075.         return S_OK;
  2076.     }
  2077.     
  2078.     // Try .media 
  2079.     lstrcpyn(strDestPath, TEXT(".\media\"), MAX_PATH);
  2080.     if( lstrlen(strDestPath) + lstrlen(strFile) < cchPath )
  2081.         lstrcat(strDestPath, strFile);
  2082.     cchDestPath = GetFullPathName(strDestPath, cchPath, strPath, &strShortNameTmp);
  2083.     file = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  2084.                        OPEN_EXISTING, 0, NULL );
  2085.     if( INVALID_HANDLE_VALUE != file )
  2086.     {
  2087.         CloseHandle( file );
  2088.         return S_OK;
  2089.     }
  2090.     // Try ..media 
  2091.     lstrcpyn(strDestPath, TEXT("..\media\"), MAX_PATH);
  2092.     if( lstrlen(strDestPath) + lstrlen(strFile) < cchPath )
  2093.         lstrcat(strDestPath, strFile);
  2094.     cchDestPath = GetFullPathName(strDestPath, cchPath, strPath, &strShortNameTmp);
  2095.     file = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  2096.                        OPEN_EXISTING, 0, NULL );
  2097.     if( INVALID_HANDLE_VALUE != file )
  2098.     {
  2099.         CloseHandle( file );
  2100.         return S_OK;
  2101.     }
  2102.     // Try ....media 
  2103.     lstrcpyn(strDestPath, TEXT("..\..\media\"), MAX_PATH);
  2104.     if( lstrlen(strDestPath) + lstrlen(strFile) < cchPath )
  2105.         lstrcat(strDestPath, strFile);
  2106.     cchDestPath = GetFullPathName(strDestPath, cchPath, strPath, &strShortNameTmp);
  2107.     file = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  2108.                        OPEN_EXISTING, 0, NULL );
  2109.     if( INVALID_HANDLE_VALUE != file )
  2110.     {
  2111.         CloseHandle( file );
  2112.         return S_OK;
  2113.     }
  2114.     // Try dxsdksamplesc++Demosdonuts4media folder
  2115.     const TCHAR* strDonutsMedia = TEXT("..\C++\Demos\Donuts4\media\");
  2116.     if( FAILED( DXUtil_GetDXSDKMediaPathCch( strDestPath, cchPath ) ) )
  2117.         return E_FAIL;
  2118.     if( lstrlen(strDestPath) + lstrlen(strDonutsMedia) < cchPath )
  2119.         lstrcat(strDestPath, strDonutsMedia);
  2120.     if( lstrlen(strDestPath) + lstrlen(strFile) < cchPath )
  2121.         lstrcat(strDestPath, strFile);
  2122.     cchDestPath = GetFullPathName(strDestPath, cchPath, strPath, &strShortNameTmp);
  2123.     file = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, 
  2124.                        OPEN_EXISTING, 0, NULL );
  2125.     if( INVALID_HANDLE_VALUE != file )
  2126.     {
  2127.         CloseHandle( file );
  2128.         return S_OK;
  2129.     }
  2130.     return E_FAIL;
  2131. }
  2132. //-----------------------------------------------------------------------------
  2133. // Name: UpdateFarthestAudioPath()
  2134. // Desc:
  2135. //-----------------------------------------------------------------------------
  2136. HRESULT CMyApplication::UpdateFarthestAudioPath()
  2137. {
  2138.     FLOAT fMax = 0.0;
  2139.     DWORD dwX;
  2140.     DWORD dwBest = 0;
  2141.     for (dwX = 0; dwX < MAX_AUDIOPATHS; dwX++)
  2142.     {
  2143.         if (m_AudioPath[dwX].m_fDistance > fMax)
  2144.         {
  2145.             fMax = m_AudioPath[dwX].m_fDistance;
  2146.             dwBest = dwX;
  2147.         }
  2148.     }
  2149.     m_pFarthestAudioPath = &m_AudioPath[dwBest];
  2150.     return S_OK;
  2151. }
  2152. //-----------------------------------------------------------------------------
  2153. // Name:
  2154. // Desc:
  2155. //-----------------------------------------------------------------------------
  2156. CD3DCamera::CD3DCamera()
  2157. {
  2158.     // Set attributes for the view matrix
  2159.     D3DXVECTOR3 vEyePt(0.0f,0.0f,0.0f);
  2160.     D3DXVECTOR3 vLookatPt(0.0f,0.0f,1.0f);
  2161.     D3DXVECTOR3 vUpVec(0.0f,1.0f,0.0f);
  2162.     SetViewParams( vEyePt, vLookatPt, vUpVec );
  2163.     // Set attributes for the projection matrix
  2164.     SetProjParams( D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
  2165. }
  2166. //-----------------------------------------------------------------------------
  2167. // Name:
  2168. // Desc:
  2169. //-----------------------------------------------------------------------------
  2170. VOID CD3DCamera::SetViewParams( D3DXVECTOR3 &vEyePt, D3DXVECTOR3& vLookatPt,
  2171.                                 D3DXVECTOR3& vUpVec )
  2172. {
  2173.     // Set attributes for the view matrix
  2174.     m_vEyePt    = vEyePt;
  2175.     m_vLookatPt = vLookatPt;
  2176.     m_vUpVec    = vUpVec;
  2177.     D3DXVECTOR3 vDir = m_vLookatPt - m_vEyePt;
  2178.     D3DXVec3Normalize( &m_vView, &vDir );
  2179.     D3DXVec3Cross( &m_vCross, &m_vView, &m_vUpVec );
  2180.     D3DXMatrixLookAtLH( &m_matView, &m_vEyePt, &m_vLookatPt, &m_vUpVec );
  2181.     D3DXMatrixInverse( &m_matBillboard, NULL, &m_matView );
  2182.     m_matBillboard._41 = 0.0f;
  2183.     m_matBillboard._42 = 0.0f;
  2184.     m_matBillboard._43 = 0.0f;
  2185. }
  2186. //-----------------------------------------------------------------------------
  2187. // Name:
  2188. // Desc:
  2189. //-----------------------------------------------------------------------------
  2190. VOID CD3DCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane,
  2191.                                    FLOAT fFarPlane )
  2192. {
  2193.     // Set attributes for the projection matrix
  2194.     m_fFOV        = fFOV;
  2195.     m_fAspect     = fAspect;
  2196.     m_fNearPlane  = fNearPlane;
  2197.     m_fFarPlane   = fFarPlane;
  2198.     D3DXMatrixPerspectiveFovLH( &m_matProj, fFOV, fAspect, fNearPlane, fFarPlane );
  2199. }