home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / rockem / rm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  13.5 KB  |  427 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: rm.cpp
  6.  *
  7.  ***************************************************************************/
  8.  
  9. // Includes....
  10. #include "rm.h"
  11. #include "directx.h"
  12. #include "mmsystem.h"
  13. #include "stdio.h"
  14. #include "control.h"
  15.  
  16. // Globals....
  17. LPDIRECT3DRMFRAME        g_lpScene = NULL;    // Scene frame
  18. LPDIRECT3DRMFRAME        g_lpCamera = NULL;    // Camera frame
  19. LPDIRECT3DRMFRAME        g_lpArena = NULL;    // Arena frame
  20. LPDIRECT3DRMFRAME        g_lpBackground = NULL;    // Background frame
  21.  
  22. LPDIRECT3DRMFRAME        g_lpPlayers = NULL;    // Encapsulating frame
  23. LPDIRECT3DRMFRAME        g_lpPlayer1 = NULL;    // Human player
  24. LPDIRECT3DRMFRAME        g_lpPlayer1HeadFrame = NULL;// Human player head frame
  25. LPDIRECT3DRMANIMATIONSET    g_lpPlayer1AnimSet = NULL;// Human player animation set
  26. LPDIRECT3DRMFRAME        g_lpPlayer2 = NULL;    // Computer player
  27. LPDIRECT3DRMFRAME        g_lpPlayer2HeadFrame = NULL;// Computer player head frame
  28. LPDIRECT3DRMANIMATIONSET    g_lpPlayer2AnimSet = NULL;// Computer player animation set
  29.  
  30. LPDIRECT3DRMFRAME        g_lpTmp = NULL;        // Temporary frame
  31.  
  32. LPDIRECT3DRMLIGHT        g_lpDir;        // Global light frame
  33.  
  34. LPDIRECT3DRMMESHBUILDER        g_lpRedDebris = NULL;    // Red debris model
  35. LPDIRECT3DRMMESHBUILDER        g_lpBlueDebris = NULL;    // Blue debris model
  36. Debris                g_debris[NUM_DEBRIS];    // Debris
  37.  
  38. LPDIRECT3DRMANIMATION        g_lpAnim = NULL;    // Intro anim
  39.  
  40. // Timing stuff
  41. D3DVALUE            g_timingDelta = D3DVAL(0.0f);
  42.  
  43. // Frame rate stuff
  44. DWORD                g_dwLastTime = 0;
  45. DWORD                g_dwCurTime = 0;
  46. DWORD                g_dwFpsTime = 0;
  47. DWORD                g_dwDeltaTime = 0;
  48. DWORD                g_dwFramesRendered = 0;
  49. DWORD                g_dwFps = 0;
  50.  
  51. // Externals....
  52. extern BOOL            g_bShowStats;        // Defined in WINMAIN.CPP
  53. extern BOOL            g_bHardware3D;        // Defined in DIRECTX.CPP
  54. extern LPDIRECT3DRM        g_lpD3DRM;        // Defined in DIRECTX.CPP
  55. extern LPDIRECT3DRMVIEWPORT    g_lpD3DRMViewport;    // Defined in DIRECTX.CPP
  56. extern LPDIRECT3DRMDEVICE    g_lpD3DRMDevice;    // Defined in DIRECTX.CPP
  57. extern LPDIRECTDRAWSURFACE    g_lpPrimary;        // Defined in DIRECTX.CPP
  58. extern LPDIRECTDRAWSURFACE    g_lpBackBuffer;        // Defined in DIRECTX.CPP
  59. extern LPDIRECTDRAWSURFACE    g_lpZBuffer;        // Defined in DIRECTX.CPP
  60. extern DWORD            g_vidModeX;        // Defined in DIRECTX.CPP
  61. extern DWORD            g_vidModeY;        // Defined in DIRECTX.CPP
  62. extern DWORD            g_vidModeBIT;        // Defined in DIRECTX.CPP
  63. extern DWORD            g_dwFontHeight;        // Defined in DIRECTX.CPP
  64. extern DWORD            g_dwAveCharWidth;    // Defined in DIRECTX.CPP
  65.  
  66. extern DWORD            g_player1health;    // Defined in CONTROL.CPP
  67. extern DWORD            g_player2health;    // Defined in CONTROL.CPP
  68.  
  69. extern DWORD            g_lbar1;        // Defined in DIRECTX.CPP
  70. extern DWORD            g_wbar1;        // Defined in DIRECTX.CPP
  71. extern DWORD            g_lbar2;        // Defined in DIRECTX.CPP
  72. extern DWORD            g_wbar2;        // Defined in DIRECTX.CPP
  73. extern DWORD            g_hbar1;        // Defined in DIRECTX.CPP
  74. extern DWORD            g_hbar2;        // Defined in DIRECTX.CPP
  75.  
  76. extern AnimArgs            g_player1AnimArgs;
  77. extern AnimArgs            g_player2AnimArgs;
  78.  
  79. //----------------------------------------------------------------------
  80. // 
  81. // Function    : InitScene
  82. //
  83. // Purpose    : Initialises Direct3D RM objects and loads scene for demo
  84. //
  85. //----------------------------------------------------------------------
  86.  
  87. BOOL InitScene()
  88. {
  89.     LPDIRECT3DRMLIGHT        pAmb;
  90.     LPDIRECT3DRMFRAME        pLight;
  91.     LPDIRECT3DRMMESHBUILDER pMeshBuilder;
  92.  
  93.     // Create the scene (parent) frame
  94.     TRY_D3DRM(g_lpD3DRM->CreateFrame(NULL, &g_lpScene))
  95.  
  96.     // Create the camera (child of g_lpScene)
  97.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpScene, &g_lpCamera))
  98.  
  99.     // Create the arena frame
  100.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpScene, &g_lpArena))
  101.  
  102.     // Create the frame that encapsulates both players
  103.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpScene, &g_lpPlayers))
  104.     
  105.     // Create player frames
  106.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpPlayers, &g_lpPlayer1))
  107.  
  108.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpPlayers, &g_lpPlayer2))
  109.     
  110.     // Create temporary frame
  111.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpScene, &g_lpTmp))
  112.     
  113.     // Create lights and position in world
  114.     TRY_D3DRM(g_lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.2), D3DVAL(0.2), D3DVAL(0.2), &pAmb))
  115.     
  116.     TRY_D3DRM(g_lpD3DRM->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVAL(0.7), D3DVAL(0.7), D3DVAL(0.7), &g_lpDir))
  117.  
  118.     // Create ambient light frame
  119.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpScene, &pLight))
  120.     
  121.     // Add the light to the frame
  122.     TRY_D3DRM(pLight->AddLight(pAmb))
  123.     
  124.     // Release the light frame
  125.     pLight->Release();    
  126.  
  127.     // Create directional light frame
  128.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpScene, &pLight))
  129.     
  130.     // Set position and orientation of directional light
  131.     pLight->SetPosition(g_lpScene, D3DVAL(1000), D3DVAL(1000), D3DVAL(1000));
  132.     pLight->SetOrientation(g_lpScene, D3DVAL(-1.0), D3DVAL(-1.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0));
  133.     
  134.     // Add the light to the frame
  135.     TRY_D3DRM(pLight->AddLight(g_lpDir))
  136.     
  137.     // Enable lights only for any object that is a child of g_lpPlayers
  138.     TRY_D3DRM(g_lpDir->SetEnableFrame(g_lpPlayers))
  139.  
  140.     // Release the light frame
  141.     pLight->Release();
  142.  
  143.     // Create mesh builder for arena
  144.     TRY_D3DRM(g_lpD3DRM->CreateMeshBuilder(&pMeshBuilder))
  145.     
  146.     // Load the arena
  147.     TRY_D3DRM(pMeshBuilder->Load("ARENA.X", NULL, D3DRMLOAD_FROMFILE, LoadTextures, NULL))
  148.     
  149.     // Make sure we use perspective correct!
  150.     pMeshBuilder->SetPerspective(TRUE);
  151.     
  152.     // Add the mesh to the scene
  153.     TRY_D3DRM(g_lpArena->AddVisual(pMeshBuilder))
  154.     
  155.     g_lpArena->SetZbufferMode(D3DRMZBUFFER_DISABLE);
  156.  
  157.     // Release the mesh builder
  158.     pMeshBuilder->Release();
  159.  
  160.     // Load player 1's model    
  161.     TRY_D3DRM(g_lpD3DRM->CreateAnimationSet(&g_lpPlayer1AnimSet))
  162.  
  163.     // Load the model and animation
  164.     TRY_D3DRM(g_lpPlayer1AnimSet->Load("SKMECH.X", NULL, D3DRMLOAD_FROMFILE, LoadTextures, NULL, g_lpPlayer1))
  165.  
  166.     // Add animation callback for player 1
  167.     g_player1AnimArgs.lpAnimSet = g_lpPlayer1AnimSet;
  168.     g_player1AnimArgs.time        = D3DVAL(0);
  169.     TRY_D3DRM(g_lpPlayer1->AddMoveCallback(Player1AnimationCallback, NULL))
  170.  
  171.     // Setup the initial position of player 1
  172.     g_lpPlayer1->SetPosition(g_lpScene, D3DVAL(0), D3DVAL(0), D3DVAL(-200));
  173.  
  174.     // Load player 2's model
  175.     TRY_D3DRM(g_lpD3DRM->CreateAnimationSet(&g_lpPlayer2AnimSet))
  176.  
  177.     // Load the model and animation
  178.     TRY_D3DRM(g_lpPlayer2AnimSet->Load("DEMECH.X", NULL, D3DRMLOAD_FROMFILE, LoadTextures, NULL, g_lpPlayer2))
  179.     
  180.     // Add animation callback for player 2
  181.     g_player2AnimArgs.lpAnimSet = g_lpPlayer2AnimSet;
  182.     g_player2AnimArgs.time        = D3DVAL(0);
  183.     TRY_D3DRM(g_lpPlayer2->AddMoveCallback(Player2AnimationCallback, NULL))    
  184.  
  185.     for (int i = 0; i < NUM_DEBRIS; i ++)
  186.     {
  187.     TRY_D3DRM(g_lpD3DRM->CreateFrame(g_lpPlayers, &g_debris[i].m_pFrame))
  188.     
  189.     g_debris[i].m_bInUse = FALSE;
  190.     }
  191.  
  192.     // Load the red debris
  193.     TRY_D3DRM(g_lpD3DRM->CreateMeshBuilder(&g_lpRedDebris))
  194.  
  195.     TRY_D3DRM(g_lpRedDebris->Load("debris_r.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
  196.     
  197.     // Load the blue debris
  198.     TRY_D3DRM(g_lpD3DRM->CreateMeshBuilder(&g_lpBlueDebris))
  199.  
  200.     TRY_D3DRM(g_lpBlueDebris->Load("debris_b.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL))
  201.  
  202.     // Setup the initial position of player 2
  203.     g_lpPlayer2->SetPosition(g_lpScene, D3DVAL(0), D3DVAL(0), D3DVAL(200));
  204.  
  205.     // Create the intro path
  206.     TRY_D3DRM(g_lpD3DRM->CreateAnimation(&g_lpAnim))
  207.  
  208.     // Setup the animation options
  209.     g_lpAnim->SetOptions(D3DRMANIMATION_OPEN | 
  210.              D3DRMANIMATION_LINEARPOSITION | 
  211.              D3DRMANIMATION_POSITION);
  212.     
  213.     // Add the starting position (as a keyframe)
  214.     g_lpAnim->AddPositionKey(D3DVAL(0), D3DVAL(200), D3DVAL(2000), D3DVAL(0));
  215.     
  216.     // Add the ending position (as a keyframe)
  217.     g_lpAnim->AddPositionKey(D3DVAL(1), D3DVAL(700), D3DVAL(100), D3DVAL(0));
  218.     
  219.     // Make the camera follow this animation
  220.     g_lpAnim->SetFrame(g_lpCamera);    
  221.  
  222.     // Retrieve player 1 and player 2's head frames    
  223.     LPDIRECT3DRMOBJECT tmp;
  224.         
  225.     TRY_D3DRM(g_lpD3DRM->GetNamedObject("x3ds_Head", &tmp))
  226.     g_lpPlayer1HeadFrame = (LPDIRECT3DRMFRAME)tmp;
  227.  
  228.     TRY_D3DRM(g_lpD3DRM->GetNamedObject("x3ds_xHead", &tmp))
  229.     g_lpPlayer2HeadFrame = (LPDIRECT3DRMFRAME)tmp;
  230.  
  231.     // Yahoo!
  232.     return TRUE;
  233. }
  234.  
  235. //----------------------------------------------------------------------
  236. // 
  237. // Function    : TermScene
  238. //
  239. // Purpose    : Destroys scene
  240. //
  241. //----------------------------------------------------------------------
  242.  
  243. void TermScene()
  244. {    
  245.     // Destroy the scene frame
  246.     if (g_lpScene)
  247.     {
  248.     g_lpScene->Release();
  249.     g_lpScene = NULL;
  250.     }
  251.  
  252.     // Destroy the animation sets
  253.     if (g_lpPlayer1AnimSet)
  254.     {
  255.     g_lpPlayer1AnimSet->Release();
  256.     g_lpPlayer1AnimSet = NULL;
  257.     }
  258.  
  259.     if (g_lpPlayer2AnimSet)
  260.     {
  261.     g_lpPlayer2AnimSet->Release();
  262.     g_lpPlayer2AnimSet = NULL;
  263.     }
  264. }
  265.  
  266. //----------------------------------------------------------------------
  267. // 
  268. // Function    : RenderScene
  269. //
  270. // Purpose    : Renders scene
  271. //
  272. //----------------------------------------------------------------------
  273.  
  274. BOOL RenderScene()
  275. {
  276.     static BOOL b = FALSE;
  277.  
  278.     // Verify both surfaces
  279.     if (!g_lpPrimary) return FALSE;
  280.  
  281.     if (!g_lpZBuffer) return FALSE;
  282.  
  283.     // Perform some timing stuff    
  284.     g_dwCurTime      = timeGetTime();
  285.     g_dwDeltaTime = g_dwCurTime - g_dwLastTime;
  286.     g_dwLastTime  = g_dwCurTime;
  287.     g_dwFpsTime  += g_dwDeltaTime;
  288.  
  289.     // Move the scene
  290.     g_lpScene->Move(D3DVAL(g_dwDeltaTime));
  291.  
  292.     if (b) {
  293.     b = FALSE;
  294.     TRY_D3DRM(g_lpD3DRMViewport->ForceUpdate(0, 0, g_vidModeX, g_vidModeY))
  295.     }
  296.  
  297.     // Restore the primary surface if it has been lost
  298.     if (g_lpPrimary->IsLost())
  299.     {
  300.         HRESULT rval = g_lpPrimary->Restore();
  301.         if (rval != DD_OK) return TRUE;
  302.         TRY_D3DRM(g_lpD3DRMViewport->ForceUpdate(0, 0, g_vidModeX, g_vidModeY))
  303.         b = TRUE;
  304.     }
  305.     
  306.     // Restore the ZBuffer if it has been lost
  307.     if (g_lpZBuffer->IsLost())
  308.     {
  309.         HRESULT rval = g_lpZBuffer->Restore();
  310.         if (rval != DD_OK) return TRUE;
  311.         TRY_D3DRM(g_lpD3DRMViewport->ForceUpdate(0, 0, g_vidModeX, g_vidModeY))
  312.     }
  313.  
  314.     // Clear the viewport ready for rendering
  315.     TRY_D3DRM(g_lpD3DRMViewport->Clear())
  316.     
  317.     // Render the scene
  318.     TRY_D3DRM(g_lpD3DRMViewport->Render(g_lpScene))
  319.  
  320.     g_dwFramesRendered ++;
  321.  
  322.     // Show stats if necessary
  323.     if (g_bShowStats)
  324.     {
  325.     // String to hold stats
  326.     char sStats[256];        
  327.  
  328.     // If 2 seconds have elapsed, calculate the frame rate
  329.     if (g_dwFpsTime > 2000)
  330.     {
  331.         g_dwFps        = g_dwFramesRendered / 2;
  332.         g_dwFramesRendered    = 0;
  333.         g_dwFpsTime        = 0;
  334.     }
  335.  
  336.     // Copy info into stat string
  337.     sprintf(sStats, "SX:%d, SY:%d, SBD:%d FPS:%d, %s", g_vidModeX, g_vidModeY, g_vidModeBIT, g_dwFps, g_bHardware3D ? "(H)" : "(S)");
  338.  
  339.     // Get a DC to the backbuffer (very useful!)
  340.     HDC hDC;
  341.     g_lpBackBuffer->GetDC(&hDC);
  342.     if (!hDC) return FALSE;
  343.  
  344.     // Use TextOut to draw the text onto the surface
  345.     DWORD dwStringPixelWidth = strlen(sStats) * g_dwAveCharWidth;
  346.  
  347.         SetBkMode( hDC, TRANSPARENT );
  348.         SetTextColor( hDC, RGB(255,255,255) );
  349.     TextOut(hDC, (g_vidModeX >> 1) - (dwStringPixelWidth >> 1), g_vidModeY - g_dwFontHeight, sStats, strlen(sStats));
  350.  
  351.     // Must release DC before calling Flip()
  352.     g_lpBackBuffer->ReleaseDC(hDC);
  353.     }
  354.  
  355.     // Draw the power bars
  356.     DDBLTFX ddBltFx;
  357.     memset(&ddBltFx, 0, sizeof(DDBLTFX));
  358.     ddBltFx.dwSize = sizeof(DDBLTFX);
  359.  
  360.     RECT rcBar1 = { g_lbar1, g_hbar1, g_lbar1 + g_wbar1, g_hbar1 + g_hbar2 };
  361.     RECT rcBar2 = { g_lbar2, g_hbar1, g_lbar2 + g_wbar2, g_hbar1 + g_hbar2 };
  362.  
  363.     switch (g_vidModeBIT)
  364.     {
  365.     case 8  : ddBltFx.dwFillColor = 253; break;
  366.     case 16 : ddBltFx.dwFillColor = 1 << 4; break;
  367.     case 24 : ddBltFx.dwFillColor = 1 << 7; break;
  368.     }
  369.     if (g_player1health > 0) {
  370.     TRY_DD(g_lpBackBuffer->Blt(&rcBar1, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddBltFx))
  371.     TRY_D3DRM(g_lpD3DRMViewport->ForceUpdate(rcBar1.left, rcBar1.top, rcBar1.right, rcBar1.bottom))
  372.     }
  373.  
  374.     switch (g_vidModeBIT)
  375.     {
  376.     case 8  : ddBltFx.dwFillColor = 254; break;
  377.     case 16 : ddBltFx.dwFillColor = 1 << 5 << 5 << 4; break;
  378.     case 24 : ddBltFx.dwFillColor = 1 << 8 << 8 << 7; break;
  379.     }    
  380.     if (g_player2health > 0) {
  381.     TRY_DD(g_lpBackBuffer->Blt(&rcBar2, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddBltFx))
  382.     TRY_D3DRM(g_lpD3DRMViewport->ForceUpdate(rcBar2.left, rcBar2.top, rcBar2.right, rcBar2.bottom))
  383.     }
  384.  
  385.     // And update the device
  386.     TRY_D3DRM(g_lpD3DRMDevice->Update())
  387.  
  388.     // Finally, flip the back buffer onto the primary surface, displaying
  389.     // the last rendered frame
  390.     TRY_DD(g_lpPrimary->Flip(NULL, DDFLIP_WAIT))
  391.  
  392.     // Yahoo!
  393.     return TRUE;
  394. }
  395.  
  396. //------------------------------------------------------------------
  397. // 
  398. // Function    : LoadTextures
  399. //
  400. // Purpose    : Loads an individual texture
  401. //
  402. // NOTE        : Textures must have a size divisible by 2 (e.g. 128x64, 256x256)
  403. //
  404. //------------------------------------------------------------------
  405.  
  406. HRESULT LoadTextures(char *sName, void *pArg, LPDIRECT3DRMTEXTURE *hTexture)
  407. {    
  408.     char *sTmpName = sName;
  409.         
  410.     // Find the extension
  411.     while(sTmpName[0] != '.') sTmpName ++;
  412.  
  413.     // Add .ppm to the picture file used by 3D Studio (.TGA, .GIF, .CEL etc)
  414.     strcpy(sTmpName, ".ppm");
  415.     
  416.     // Load the texture
  417.     if (FAILED(g_lpD3DRM->LoadTexture(sName, hTexture))) return -1;
  418.  
  419.     if (!strcmp(sName, "gdk_fill.ppm"))
  420.     {
  421.     (*hTexture)->SetShades(1);
  422.     }
  423.  
  424.     return 0;
  425. }
  426.  
  427.