home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / ROCKEM / CONTROL.CPP < prev    next >
C/C++ Source or Header  |  1996-08-28  |  45KB  |  1,216 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: control.cpp
  6.  *
  7.  ***************************************************************************/
  8.  
  9. // Includes....
  10. #include "rm.h"
  11. #include "control.h"
  12. #include "directx.h"
  13.  
  14. // Defines....
  15. #define MOVE_NORMAL                     D3DVAL(10)
  16. #define MOVE_FAST                       D3DVAL(20)
  17.  
  18. #define MIN_DIST_TO_OPPONENT            D3DVAL(100)
  19.  
  20. #define PLAYER_MOVE_FORWARD             VK_UP
  21. #define PLAYER_MOVE_BACKWARD            VK_DOWN
  22. #define PLAYER_BLOCK                    VK_CONTROL
  23. #define PLAYER_ATTACK                   VK_SPACE
  24.  
  25. #define CAM_BOTH_IN_VIEW                VK_F1
  26. #define CAM_OVER_THE_SHOULDER           VK_F2
  27. #define CAM_PILOT                       VK_F3
  28.  
  29. #define NUM_BOB_FRAMES                  D3DVAL(30)
  30. #define NUM_DEAD_FRAMES                 D3DVAL(66)
  31. #define NUM_PUNCH_FRAMES                D3DVAL(29)
  32. #define NUM_BEEN_HIT_FRAMES             D3DVAL(14)
  33. #define NUM_BLOCKING_FRAMES             D3DVAL(16)
  34. #define NUM_VICTORY_FRAMES              D3DVAL(55)
  35.  
  36. #define BOB_START                       D3DVAL(1)
  37. #define DEAD_START                      D3DVAL(94)
  38. #define DEAD_HIT_GROUND                 D3DVAL(115)
  39. #define PUNCH_START                     D3DVAL(31)
  40. #define PUNCH_ARM_COCKED                D3DVAL(50)
  41. #define BLOCK_START                     D3DVAL(77)
  42. #define BEEN_HIT_START                  D3DVAL(62)
  43. #define HEAD_RETURNING                  D3DVAL(68)
  44. #define VICTORY_START                   D3DVAL(161)
  45.  
  46. #define EDGE_LEFT                       D3DVAL(-600)
  47. #define EDGE_RIGHT                      D3DVAL(600)
  48.  
  49. // Globals....
  50.  
  51. // States
  52. AppState                g_appState = DOING_INTRO;
  53. PlayerState             g_oppState = CAUTIOUS;
  54. CameraState             g_camState = BOTH_IN_VIEW;
  55.  
  56. PlayerActionState       g_player1State = BOBBING;
  57. PlayerActionState       g_player2State = BOBBING;
  58.  
  59. AnimArgs                g_player1AnimArgs;
  60. AnimArgs                g_player2AnimArgs;
  61.  
  62. BOOL                    g_bPlayer1Attacking = FALSE;
  63. BOOL                    g_bPlayer1Blocking  = FALSE;
  64.  
  65. DWORD                   g_player1health = 100;
  66. DWORD                   g_player2health = 100;
  67.  
  68. // Timed lengths for each animation in milliseconds
  69. #define BOB_TIME_MS     D3DVAL(500)
  70. #define PUNCH_TIME_MS   D3DVAL(600)
  71. #define BLOCK_TIME_MS   D3DVAL(500)
  72. #define HIT_TIME_MS     D3DVAL(500)
  73. #define DEAD_TIME_MS    D3DVAL(4000)
  74. #define VICTORY_TIME_MS D3DVAL(3000)
  75.  
  76. // Timing deltas, used for scaling animation to frame rate
  77. D3DVALUE                g_bobDelta     = NUM_BOB_FRAMES / BOB_TIME_MS;
  78. D3DVALUE                g_attackDelta  = NUM_PUNCH_FRAMES / PUNCH_TIME_MS;
  79. D3DVALUE                g_blockDelta   = NUM_BLOCKING_FRAMES / BLOCK_TIME_MS;
  80. D3DVALUE                g_hitDelta     = NUM_BEEN_HIT_FRAMES / HIT_TIME_MS;
  81. D3DVALUE                g_deadDelta    = NUM_DEAD_FRAMES / DEAD_TIME_MS;
  82. D3DVALUE                g_victoryDelta = NUM_DEAD_FRAMES / DEAD_TIME_MS;
  83.  
  84. // Externals....
  85. extern LPDIRECT3DRM             g_lpD3DRM;
  86. extern LPDIRECT3DRMFRAME        g_lpScene;
  87. extern LPDIRECT3DRMFRAME        g_lpCamera;
  88. extern LPDIRECT3DRMFRAME        g_lpPlayer1;
  89. extern LPDIRECT3DRMFRAME        g_lpPlayer1HeadFrame;
  90. extern LPDIRECT3DRMFRAME        g_lpPlayer2;
  91. extern LPDIRECT3DRMFRAME        g_lpPlayer2HeadFrame;
  92. extern LPDIRECT3DRMFRAME        g_lpTmp;
  93. extern LPDIRECT3DRMANIMATION    g_lpAnim;
  94. extern LPDIRECT3DRMMESHBUILDER  g_lpRedDebris;
  95. extern LPDIRECT3DRMMESHBUILDER  g_lpBlueDebris;
  96. extern Debris                   g_debris[NUM_DEBRIS];
  97. extern LPDIRECTSOUND3DLISTENER  g_lpDs3dListener; // Defined in DIRECTX.CPP
  98.  
  99.  
  100. //----------------------------------------------------------------------
  101. // 
  102. // Function     : IsKeyDown()
  103. //
  104. // Purpose      : Returns TRUE if specified key is being pressed
  105. //
  106. //----------------------------------------------------------------------
  107.  
  108. BOOL IsKeyDown(int virtKeyCode)
  109. {
  110.     if (GetAsyncKeyState(virtKeyCode) & 0x8000) return TRUE;
  111.  
  112.     return FALSE;
  113. }
  114.  
  115. //----------------------------------------------------------------------
  116. // 
  117. // Function     : Player1AnimationCallback()
  118. //
  119. // Purpose      : Animation call back for player 1
  120. //
  121. //----------------------------------------------------------------------
  122.  
  123. void CDECL Player1AnimationCallback(LPDIRECT3DRMFRAME obj, void* arg, D3DVALUE delta)
  124. {       
  125.     D3DVALUE time = g_player1AnimArgs.time;
  126.     D3DVECTOR player1pos;
  127.     D3DVECTOR player2pos;
  128.     
  129.     // Booleans to help with sound playing
  130.     static BOOL bHitGround              = FALSE;
  131.     static BOOL bPlayedWhoosh   = FALSE;
  132.  
  133.     // Get the players positions
  134.     g_lpPlayer1->GetPosition(g_lpScene, &player1pos);   
  135.     g_lpPlayer2->GetPosition(g_lpScene, &player2pos);
  136.     
  137.     // Compute distance between players
  138.     D3DVALUE curDist = player2pos.z - player1pos.z;
  139.  
  140.     // Do something based upon the state of player 1
  141.     switch (g_player1State)
  142.     {
  143.         case BOBBING :
  144.         {       
  145.             // Forward the bobbing animation time
  146.             g_player1AnimArgs.lpAnimSet->SetTime(time);                 
  147.             time += (g_bobDelta * delta);
  148.             
  149.             // Reset if animation has ended
  150.             if (time > BOB_START + NUM_BOB_FRAMES) time = BOB_START;
  151.             
  152.             // Record the new time
  153.             g_player1AnimArgs.time = time;
  154.         }
  155.         break;
  156.  
  157.         case PUNCHING :
  158.         {
  159.             // Forward the punching animation time
  160.             g_player1AnimArgs.lpAnimSet->SetTime(time);
  161.             time += (g_attackDelta * delta);
  162.  
  163.             // Play a whoosh sound if player 1's arm has gone back and is about to punch
  164.             if ((time > PUNCH_ARM_COCKED) && (!bPlayedWhoosh))
  165.             {
  166.                 // Play the whoosh
  167.                 PlaySoundDS(rand() % 2 == 0 ? WHOOSH1 : WHOOSH2,player1pos);                               
  168.                 bPlayedWhoosh = TRUE;
  169.             }
  170.  
  171.             // If the punch has played, see if we hit the opponent
  172.             if (time > PUNCH_START + NUM_PUNCH_FRAMES) 
  173.             {
  174.                 // Reset player 1's state to BOBBING
  175.                 time               = BOB_START;
  176.                 g_player1State = BOBBING;
  177.                 bPlayedWhoosh  = FALSE;
  178.  
  179.                 // Play a servo sound
  180.                 PlaySoundDS(SERVO_DOWN_1,player1pos);
  181.  
  182.                 // Now, decide whether we have hit the other player
  183.                 if (curDist < MIN_DIST_TO_OPPONENT + D3DVAL(20))
  184.                 {               
  185.                     // The opponent may be blocking
  186.                     if ((g_player2State == BLOCKING) && 
  187.                         (g_player2AnimArgs.time > BLOCK_START + (NUM_BLOCKING_FRAMES / D3DVAL(2)))) 
  188.                     {
  189.                         // The opponent blocked the punch, so play the block sound
  190.                         PlaySoundDS(BLOCK1 + (rand() % 3),player2pos);
  191.                         break;
  192.                     }
  193.  
  194.                     // We're within the striking distance
  195.                     if (g_player2health == 0) return;
  196.  
  197.                     // Add some debris into the scene to register a hit and play a sound        
  198.                     D3DVECTOR debrisOrg = player1pos;
  199.                     D3DVECTOR debrisVel = { D3DVAL(0), D3DVAL(0), D3DVAL(-10) };
  200.                     
  201.                     debrisOrg.x += D3DVAL(40);
  202.                     debrisOrg.y += D3DVAL(40);
  203.                     debrisOrg.z += D3DVAL(90);
  204.                     
  205.                     // Add some debris
  206.                     AddDebris(debrisOrg, debrisVel, g_lpRedDebris);
  207.  
  208.                     // Decrease the opponents health
  209.                     if (g_player2health > 0) g_player2health -= 10;
  210.                                             
  211.                     if (g_player2health == 0)
  212.                     {
  213.                         // The opponent has died!
  214.                         g_player2State = DEAD;
  215.                         g_player2AnimArgs.time = DEAD_START;
  216.                         g_player2AnimArgs.lpAnimSet->SetTime(DEAD_START);
  217.                         PlaySoundDS(HEAD_SPRING,player2pos);
  218.                         
  219.                         // And the player has victory!
  220.                         g_player1State = VICTORY;
  221.                         g_player1AnimArgs.time = VICTORY_START;
  222.                         g_player1AnimArgs.lpAnimSet->SetTime(VICTORY_START);
  223.  
  224.                         PlaySoundDS(VICTORY_YEAH,player1pos);
  225.  
  226.                         return;
  227.                     }
  228.  
  229.                     // Play a punch sound
  230.                     PlaySoundDS(rand() % 2 == 0 ? PLAYER1_PUNCH1 : PLAYER1_PUNCH2,player2pos);
  231.  
  232.                     // Recalculate the power bars
  233.                     RecalcPowerBars(g_player1health, g_player2health);
  234.                     
  235.                     // Make sure we force the camera to the correct place
  236.                     PositionCamera();
  237.  
  238.                     // Setup the opponents animation and state
  239.                     g_player2State = BEEN_HIT;
  240.                     g_player2AnimArgs.time = BEEN_HIT_START;
  241.                     g_player2AnimArgs.lpAnimSet->SetTime(BEEN_HIT_START);
  242.                     
  243.                     // What should the opponent do?
  244.                     if (rand() % 10 < 2)
  245.                     {
  246.                         // Make the opponent defensive
  247.                         g_oppState = DEFENSIVE;
  248.                     }
  249.  
  250.                     // Play the ouch sound
  251.                     PlaySoundDS(PLAYER2_OUCH,player1pos);
  252.                 }
  253.             }
  254.  
  255.             // Record the new animation time
  256.             g_player1AnimArgs.time = time;
  257.         }
  258.         break;
  259.         
  260.         case BLOCKING : 
  261.         {
  262.             // Forward the blocking animation time
  263.             g_player1AnimArgs.lpAnimSet->SetTime(time);
  264.             
  265.             // Hold the block up if CTRL is held down
  266.             if (GetAsyncKeyState(PLAYER_BLOCK) & 0x8000)
  267.             {
  268.                 if (time < BLOCK_START + (NUM_BLOCKING_FRAMES / 2)) time += (g_blockDelta * delta);
  269.             }
  270.             else
  271.             {
  272.                 time += (g_blockDelta * delta);
  273.             }
  274.  
  275.             // Reset player 1's state to BOBBING if the animation has ended
  276.             if (time > BLOCK_START + NUM_BLOCKING_FRAMES) 
  277.             {
  278.                 time            = BOB_START;
  279.                 g_player1State  = BOBBING;
  280.             }
  281.  
  282.             // Record the new animation time
  283.             g_player1AnimArgs.time = time;
  284.         }
  285.         break;
  286.  
  287.         case BEEN_HIT :
  288.         {
  289.             // Forward the been hit animation time
  290.             g_player1AnimArgs.lpAnimSet->SetTime(time);
  291.             time += (g_hitDelta * delta);
  292.  
  293.             if (player1pos.z > EDGE_LEFT) g_lpPlayer1->SetPosition(g_lpScene, player1pos.x, player1pos.y, player1pos.z - D3DVAL(5));
  294.             PositionCamera();
  295.  
  296.             // Reset player 1's state to BOBBING if the animation has ended
  297.             if (time > BEEN_HIT_START + NUM_BEEN_HIT_FRAMES) 
  298.             {
  299.                 time            = BOB_START;
  300.                 g_player1State  = BOBBING;
  301.             }
  302.             
  303.             // Record the new animation time
  304.             g_player1AnimArgs.time = time;
  305.         }
  306.         break;
  307.         
  308.         case DEAD :
  309.         {
  310.             // Forward the death animation time
  311.             g_player1AnimArgs.lpAnimSet->SetTime(time);
  312.             time += (g_deadDelta * delta);
  313.  
  314.             // Play a crash sound if the animation has passes the DEAD_HIT_GROUND frame
  315.             if ((time > DEAD_HIT_GROUND) && (!bHitGround))
  316.             {
  317.                 bHitGround = TRUE;
  318.                 PlaySoundDS(BLOCK3,player1pos);
  319.             }
  320.  
  321.             // Reset player 1's state to BOBBING if the animation has ended
  322.             if (time > DEAD_START + NUM_DEAD_FRAMES) 
  323.             {
  324.                 time            = BOB_START;
  325.                 g_player1State  = BOBBING;
  326.                 g_player1health = 100;
  327.                 bHitGround      = FALSE;
  328.  
  329.                 RecalcPowerBars(g_player1health, g_player2health);
  330.             }
  331.             
  332.             // Record the new animation time
  333.             g_player1AnimArgs.time = time;
  334.  
  335.             // Position the camera correctly
  336.             PositionCamera();
  337.         }
  338.         break;
  339.  
  340.         case VICTORY :
  341.         {
  342.             // Forward the victory animation time
  343.             g_player1AnimArgs.lpAnimSet->SetTime(time);
  344.             time += (g_victoryDelta * delta);
  345.  
  346.             if (time > VICTORY_START + NUM_VICTORY_FRAMES) 
  347.             {
  348.                 time            = BOB_START;
  349.                 g_player1State  = BOBBING;
  350.             }
  351.             g_player1AnimArgs.time = time;
  352.  
  353.             PositionCamera();
  354.         }
  355.         break;
  356.     }
  357. }
  358.  
  359. //----------------------------------------------------------------------
  360. // 
  361. // Function     : Player2AnimationCallback()
  362. //
  363. // Purpose      : Animation call back for player 2
  364. //
  365. //----------------------------------------------------------------------
  366.  
  367. void CDECL Player2AnimationCallback(LPDIRECT3DRMFRAME obj, void* arg, D3DVALUE delta)
  368. {
  369.     D3DVALUE time = g_player2AnimArgs.time;
  370.     D3DVECTOR player1pos;
  371.     D3DVECTOR player2pos;
  372.  
  373.     // Booleans to help with sound playing
  374.     static BOOL bHitGround              = FALSE;
  375.     static BOOL bPlayedWhoosh   = FALSE;
  376.  
  377.     // Get the players positions
  378.     g_lpPlayer1->GetPosition(g_lpScene, &player1pos);   
  379.     g_lpPlayer2->GetPosition(g_lpScene, &player2pos);
  380.  
  381.     // Compute distance between players
  382.     D3DVALUE curDist = player2pos.z - player1pos.z;
  383.  
  384.     // Do something based upon the state of player 1
  385.     switch (g_player2State)
  386.     {
  387.         case BOBBING :
  388.         {       
  389.             // Forward the bobbing animation time
  390.             g_player2AnimArgs.lpAnimSet->SetTime(time);
  391.             time += (g_bobDelta * delta);
  392.  
  393.             // Reset if animation has ended
  394.             if (time > BOB_START + NUM_BOB_FRAMES) time = BOB_START;
  395.  
  396.             // Record the new time
  397.             g_player2AnimArgs.time = time;
  398.         }
  399.         break;
  400.  
  401.         case PUNCHING :
  402.         {
  403.             // Forward the punching animation time
  404.             g_player2AnimArgs.lpAnimSet->SetTime(time);
  405.             time += (g_attackDelta * delta);
  406.  
  407.             // Play a whoosh sound if player 2's arm has gone back and is about to punch
  408.             if ((time > PUNCH_ARM_COCKED) && (!bPlayedWhoosh))
  409.             {
  410.                 // Play the whoosh
  411.                 PlaySoundDS(rand() % 2 == 0 ? WHOOSH1 : WHOOSH2,player2pos);                               
  412.                 bPlayedWhoosh = TRUE;
  413.             }
  414.     
  415.             // If the punch has played, see if we hit the opponent
  416.             if (time > PUNCH_START + NUM_PUNCH_FRAMES) 
  417.             {
  418.                 time = BOB_START;
  419.                 g_player2State = BOBBING;
  420.                 bPlayedWhoosh  = FALSE;
  421.                 
  422.                 // Play a servo sound
  423.                 PlaySoundDS(SERVO_DOWN_2,player2pos);
  424.  
  425.                 // Now, decide whether we have hit the other player
  426.                 if (curDist < MIN_DIST_TO_OPPONENT + D3DVAL(20))
  427.                 {               
  428.                     // The opponent may be blocking
  429.                     if ((g_player1State == BLOCKING) && 
  430.                         (g_player1AnimArgs.time > BLOCK_START + (NUM_BLOCKING_FRAMES / D3DVAL(2)))) 
  431.                     {
  432.                         // The opponent blocked the punch, so play the block sound
  433.                         PlaySoundDS(BLOCK1 + (rand() % 3),player1pos);
  434.                         break;
  435.                     }
  436.  
  437.                     // We're within the striking distance
  438.                     if (g_player1health <= 0) return;
  439.  
  440.                     // We're within the striking distance
  441.                     // Add some debris into the scene to register a hit and play a sound        
  442.                     D3DVECTOR debrisOrg = player1pos;
  443.                     D3DVECTOR debrisVel = { D3DVAL(0), D3DVAL(0), D3DVAL(10) };
  444.                     
  445.                     debrisOrg.x += D3DVAL(-40);
  446.                     debrisOrg.y += D3DVAL(40);
  447.                     debrisOrg.z += D3DVAL(-10);
  448.                     
  449.                     // Add some debris
  450.                     AddDebris(debrisOrg, debrisVel, g_lpBlueDebris);
  451.  
  452.                     // Play a punch sound
  453.                     PlaySoundDS(rand() % 2 == 0 ? PLAYER2_PUNCH1 : PLAYER2_PUNCH2,player1pos);
  454.  
  455.                     // Decrease the opponents health
  456.                     if (g_player1health > 0) g_player1health -= 10;
  457.  
  458.                     if (g_player1health == 0)
  459.                     {
  460.                         // The player has died!
  461.                         g_player1State = DEAD;
  462.                         g_player1AnimArgs.time = DEAD_START;
  463.                         g_player1AnimArgs.lpAnimSet->SetTime(DEAD_START);
  464.                         PlaySoundDS(HEAD_SPRING,player1pos);
  465.  
  466.                         // And the opponent has victory!
  467.                         g_player2State = VICTORY;
  468.                         g_player2AnimArgs.time = VICTORY_START;
  469.                         g_player2AnimArgs.lpAnimSet->SetTime(VICTORY_START);
  470.  
  471.                         // The crowd is not happy....
  472.                         PlaySoundDS(VICTORY_BOO,player2pos);
  473.  
  474.                         return;
  475.                     }
  476.  
  477.                     // Recalculate the power bars
  478.                     RecalcPowerBars(g_player1health, g_player2health);
  479.                     
  480.                     // Force a camera positional update
  481.                     PositionCamera();
  482.                     
  483.                     if (g_player1State != BEEN_HIT)
  484.                     {
  485.                         // Change player 1's state to BEEN_HIT,
  486.                         g_player1State = BEEN_HIT;
  487.  
  488.                         // And set the animation time
  489.                         g_player1AnimArgs.time = BEEN_HIT_START;
  490.                         g_player1AnimArgs.lpAnimSet->SetTime(BEEN_HIT_START);                                           
  491.                     }
  492.  
  493.                     // Play the ouch sound
  494.                     PlaySoundDS(PLAYER1_OUCH,player1pos);
  495.                 }
  496.             }
  497.  
  498.             // Record the new animation time
  499.             g_player2AnimArgs.time = time;
  500.         }
  501.         break;
  502.  
  503.         case BEEN_HIT :
  504.         {
  505.             // Forward the been hit animation time
  506.             g_player2AnimArgs.lpAnimSet->SetTime(time);
  507.             time += (g_hitDelta * delta);
  508.             
  509.             // Move the player
  510.             if (player2pos.z < EDGE_RIGHT) g_lpPlayer2->SetPosition(g_lpScene, player2pos.x, player2pos.y, player2pos.z + D3DVAL(5));
  511.             
  512.             // Force a camera position update
  513.             PositionCamera();
  514.  
  515.             // Reset to BOBBING if animation has ended
  516.             if (time > BEEN_HIT_START + NUM_BEEN_HIT_FRAMES) 
  517.             {
  518.                 time = BOB_START;
  519.                 g_player2State = BOBBING;
  520.             }
  521.             
  522.             // Record the new animation time
  523.             g_player2AnimArgs.time = time;
  524.         }
  525.         break;
  526.  
  527.         case BLOCKING : 
  528.         {
  529.             // Forward the blocking animation time
  530.             g_player2AnimArgs.lpAnimSet->SetTime(time);
  531.             time += (g_blockDelta * delta);
  532.  
  533.             // Reset to BOBBING if animation has ended
  534.             if (time > BLOCK_START + NUM_BLOCKING_FRAMES) 
  535.             {
  536.                 time            = BOB_START;
  537.                 g_player2State  = BOBBING;
  538.                 g_oppState      = AGGRESSIVE;
  539.             }
  540.             
  541.             // Record the new animation time
  542.             g_player2AnimArgs.time = time;
  543.         }
  544.         break;
  545.  
  546.         case DEAD :
  547.         {
  548.             // Forward the death animation time
  549.             g_player2AnimArgs.lpAnimSet->SetTime(time);
  550.             time += (g_deadDelta * delta);
  551.  
  552.             // Play the BLOCK3 sound when the opponent hits the ground
  553.             if ((time > DEAD_HIT_GROUND) && (!bHitGround))
  554.             {
  555.                 bHitGround = TRUE;
  556.                 PlaySoundDS(BLOCK3,player2pos);
  557.             }
  558.  
  559.             // Reset to BOBBING if the animation has ended
  560.             if (time > DEAD_START + NUM_DEAD_FRAMES) 
  561.             {
  562.                 time            = BOB_START;
  563.                 g_player2State  = BOBBING;
  564.                 g_player2health = 100;
  565.                 bHitGround      = FALSE;
  566.  
  567.                 // Recalculate the power bars
  568.                 RecalcPowerBars(g_player1health, g_player2health);
  569.             }
  570.             // Record the new animation time
  571.             g_player2AnimArgs.time = time;
  572.  
  573.             // Force a camera position update
  574.             PositionCamera();
  575.         }
  576.         break;
  577.  
  578.         case VICTORY :
  579.         {
  580.             // Forward the victory animation time
  581.             g_player2AnimArgs.lpAnimSet->SetTime(time);
  582.             time += (g_victoryDelta * delta);
  583.  
  584.             if (time > VICTORY_START + NUM_VICTORY_FRAMES) 
  585.             {
  586.                 time            = BOB_START;
  587.                 g_player2State  = BOBBING;
  588.             }
  589.             
  590.             // Record the new animation time
  591.             g_player2AnimArgs.time = time;
  592.  
  593.             // Force a camera position update
  594.             PositionCamera();
  595.         }
  596.         break;
  597.     }
  598. }
  599.  
  600. //----------------------------------------------------------------------
  601. // 
  602. // Function     : CheckInputAndUpdate()
  603. //
  604. // Purpose      : Checks input, updates scene, moves player(s)
  605. //
  606. //----------------------------------------------------------------------
  607.  
  608. void CheckInputAndUpdate()
  609. {               
  610.     D3DVECTOR player1pos;
  611.     D3DVECTOR player2pos;
  612.     D3DVECTOR camPos;
  613.  
  614.     // Run intro
  615.     if (g_appState == DOING_INTRO)
  616.     {
  617.             RunIntro();
  618.             return;
  619.     }
  620.  
  621.     // Transition camera
  622.     if (g_appState == BETWEEN_CAM_VIEWS)
  623.     {
  624.             TransitionCamera();
  625.             return;
  626.     }
  627.  
  628.     // Get the players positions
  629.     g_lpPlayer1->GetPosition(g_lpScene, &player1pos);   
  630.     g_lpPlayer2->GetPosition(g_lpScene, &player2pos);
  631.  
  632.     // Get the camera's position
  633.     g_lpCamera->GetPosition(g_lpScene, &camPos);
  634.  
  635.     // Calculate distance between players
  636.     D3DVALUE curDist = player2pos.z - player1pos.z;
  637.  
  638.     // Move player forward
  639.     if ((IsKeyDown(PLAYER_MOVE_FORWARD)) && (g_player1State != VICTORY) && (g_player1State != DEAD))
  640.     {
  641.             // Make sure the player can only move so close to the opponent
  642.             if (curDist > MIN_DIST_TO_OPPONENT)
  643.             {
  644.                     // Move the player
  645.                     g_lpPlayer1->SetPosition(g_lpScene, player1pos.x, player1pos.y, player1pos.z + MOVE_NORMAL);
  646.  
  647.                     // Force a camera position update
  648.                     PositionCamera();
  649.  
  650.                     // Play a servo sound
  651.                     PlaySoundDS(SERVO_UP_3,player1pos);
  652.                     
  653.                     // Play a walk sound
  654.                     PlaySoundDS(PLAYER1_WALK,player1pos);
  655.             }
  656.     }
  657.  
  658.     // Move player backward
  659.     if ((IsKeyDown(PLAYER_MOVE_BACKWARD)) && (g_player1State != VICTORY) && (g_player1State != DEAD))
  660.     {
  661.             // Make sure the player can't run off the arena
  662.             if (player1pos.z > EDGE_LEFT)
  663.             {
  664.                     // Move the player
  665.                     g_lpPlayer1->SetPosition(g_lpScene, player1pos.x, player1pos.y, player1pos.z - MOVE_NORMAL);
  666.                     
  667.                     // Force a camera position update
  668.                     PositionCamera();
  669.  
  670.                     // Play a servo sound
  671.                     PlaySoundDS(SERVO_UP_3,player1pos);
  672.  
  673.                     // Play a walk sound
  674.                     PlaySoundDS(PLAYER1_WALK,player1pos);
  675.             }
  676.     }
  677.  
  678.     // Initiate a player attack
  679.     if ((!g_bPlayer1Attacking) && (!g_bPlayer1Blocking) && (IsKeyDown(PLAYER_ATTACK)))
  680.     {
  681.             if ((g_player1State != PUNCHING) && (g_player1State != DEAD) && (g_player1State != VICTORY))
  682.             {
  683.                     // Set the player state to punching
  684.                     g_player1State = PUNCHING;
  685.                     
  686.                     // Set up the correct time for the animation
  687.                     g_player1AnimArgs.time = D3DVAL(PUNCH_START);
  688.                     g_player1AnimArgs.lpAnimSet->SetTime(D3DVAL(PUNCH_START));
  689.                                     
  690.                     g_bPlayer1Attacking = TRUE;
  691.                     
  692.                     // Play a servo sound
  693.                     PlaySoundDS(SERVO_UP_1,player1pos);
  694.             }
  695.     }
  696.  
  697.     // Reset the attacking flag if the PLAYER_ATTACK key is not pressed anymore
  698.     if ((g_bPlayer1Attacking) && (!IsKeyDown(PLAYER_ATTACK)))
  699.     {
  700.             g_bPlayer1Attacking = FALSE;
  701.     }
  702.  
  703.     // Initiate a player block
  704.     if ((!g_bPlayer1Blocking) && (!g_bPlayer1Attacking) && (IsKeyDown(PLAYER_BLOCK)))
  705.     {
  706.             if ((g_player1State != BLOCKING) && (g_player1State != DEAD) && (g_player1State != VICTORY))
  707.             {
  708.                     // Set the player state to blocking
  709.                     g_player1State = BLOCKING;
  710.                     
  711.                     // Set up the correct time for the animation
  712.                     g_player1AnimArgs.time = D3DVAL(BLOCK_START);
  713.                     g_player1AnimArgs.lpAnimSet->SetTime(D3DVAL(BLOCK_START));
  714.                             
  715.                     // Don't allow any more blocking
  716.                     g_bPlayer1Blocking = TRUE;
  717.                     
  718.                     // Play a servo sound
  719.                     PlaySoundDS(SERVO_UP_1,player1pos);
  720.             }   
  721.     }
  722.  
  723.     // Reset the blocking flag if the PLAYER_BLOCK key is no longer held down
  724.     if ((g_bPlayer1Blocking) && (!IsKeyDown(PLAYER_BLOCK)))
  725.     {
  726.             g_bPlayer1Blocking = FALSE;
  727.     }
  728.  
  729.     // Transition to the BOTH_IN_VIEW camera view
  730.     if ((IsKeyDown(CAM_BOTH_IN_VIEW)) && (g_camState != BOTH_IN_VIEW))
  731.     {
  732.             // Create transition animation
  733.             if (!FAILED(g_lpD3DRM->CreateAnimation(&g_lpAnim)))
  734.             {
  735.                     // Setup the animation options
  736.                     g_lpAnim->SetOptions(D3DRMANIMATION_OPEN | 
  737.                                                              D3DRMANIMATION_LINEARPOSITION | 
  738.                                                              D3DRMANIMATION_POSITION);
  739.  
  740.                     // Make midway vector between both players, this is what the camera will focus on
  741.                     D3DVECTOR vMidPoint;
  742.                     vMidPoint.x = 0.0f;
  743.                     vMidPoint.y = 0.0f;
  744.                     vMidPoint.z = (player1pos.z + player2pos.z) / D3DVAL(2);
  745.                     
  746.                     // Calculate vector that will keep both players in sight
  747.                     D3DVECTOR vNewCam;
  748.                     vNewCam.x = (float)abs((int)player2pos.z - (int)player1pos.z) + D3DVAL(300);
  749.                     vNewCam.y = camPos.y;
  750.                     vNewCam.z = vMidPoint.z;
  751.                     
  752.                     // Add the keyframes to the animation
  753.                     g_lpAnim->AddPositionKey(D3DVAL(0), camPos.x, camPos.y, camPos.z);
  754.                     g_lpAnim->AddPositionKey(D3DVAL(1), vNewCam.x, vNewCam.y, vNewCam.z);
  755.                     
  756.                     // Setup the initial position
  757.                     g_lpTmp->SetPosition(g_lpScene, vMidPoint.x, vMidPoint.y, vMidPoint.z);
  758.                     
  759.                     // And attach the camera to the animation
  760.                     g_lpAnim->SetFrame(g_lpCamera);
  761.  
  762.                     g_appState = BETWEEN_CAM_VIEWS;
  763.             }
  764.             else
  765.             {
  766.                     // Create animation failed so just set the camera position
  767.                     g_lpCamera->SetPosition(g_lpScene, D3DVAL(200), D3DVAL(100), player1pos.z + MOVE_NORMAL - D3DVAL(400));
  768.                     g_lpCamera->LookAt(g_lpPlayer2, g_lpScene, D3DRMCONSTRAIN_Z);               
  769.                     PositionCamera();                   
  770.             }
  771.  
  772.             g_camState = BOTH_IN_VIEW;
  773.     }
  774.     
  775.     // Transition to the OVER_SHOULDER camera view
  776.     if ((IsKeyDown(CAM_OVER_THE_SHOULDER)) && (g_camState != OVER_SHOULDER))
  777.     {
  778.         if (!FAILED(g_lpD3DRM->CreateAnimation(&g_lpAnim)))
  779.         {
  780.             // Setup the animation options
  781.             g_lpAnim->SetOptions(D3DRMANIMATION_OPEN | 
  782.                                  D3DRMANIMATION_LINEARPOSITION | 
  783.                                  D3DRMANIMATION_POSITION);
  784.  
  785.             // Add the keyframes to the animation                       
  786.             g_lpAnim->AddPositionKey(D3DVAL(0), camPos.x, camPos.y, camPos.z);
  787.             g_lpAnim->AddPositionKey(D3DVAL(1), D3DVAL(200), D3DVAL(100), player1pos.z - D3DVAL(300));
  788.             
  789.             // Setup the initial position
  790.             g_lpTmp->SetPosition(g_lpScene, player2pos.x, player2pos.y, player2pos.z);
  791.             
  792.             // And attach the camera to the animation
  793.             g_lpAnim->SetFrame(g_lpCamera);
  794.  
  795.             g_appState = BETWEEN_CAM_VIEWS;
  796.         }
  797.         else
  798.         {
  799.             // Create animation failed so just set the camera position
  800.             PositionCamera();
  801.         }
  802.                                 
  803.         g_camState = OVER_SHOULDER;
  804.     }
  805.  
  806.     // Transition to the PILOT_VIEW camera view
  807.     if ((IsKeyDown(CAM_PILOT)) && (g_camState != PILOT_VIEW))
  808.     {
  809.         PositionCamera();
  810.         g_camState = PILOT_VIEW;
  811.     }
  812.  
  813.     // Update the opponent
  814.     UpdateOpponent();
  815.  
  816.     // Update any debris in the world
  817.     UpdateDebris();
  818. }
  819.  
  820. //----------------------------------------------------------------------
  821. // 
  822. // Function     : UpdateOpponent()
  823. //
  824. // Purpose      : Updates opponent
  825. //
  826. //----------------------------------------------------------------------
  827.  
  828. void UpdateOpponent()
  829. {
  830.     D3DVECTOR player1pos;
  831.     D3DVECTOR player2pos;       
  832.  
  833.     if (g_player2State != BOBBING) return;
  834.  
  835.     // Random value to determine what the opponent should do based upon its state
  836.     int r = rand() % 100;
  837.  
  838.     // Get the players positions
  839.     g_lpPlayer1->GetPosition(g_lpScene, &player1pos);   
  840.     g_lpPlayer2->GetPosition(g_lpScene, &player2pos);
  841.  
  842.     // Calculate distance betweens players
  843.     D3DVALUE curDist = player2pos.z - player1pos.z;
  844.     
  845.     // There is always a chance to block the player
  846.     if ((r < 15) && (g_player1State == PUNCHING) && (g_player2State == BOBBING))
  847.     {
  848.         // Set the opponents state to BLOCKING ans start the animation
  849.         g_player2State = BLOCKING;
  850.         g_player2AnimArgs.time = BLOCK_START;
  851.         g_player2AnimArgs.lpAnimSet->SetTime(BLOCK_START);
  852.         
  853.         // Play a servo sound
  854.         PlaySoundDS(SERVO_UP_2,player2pos);
  855.         return;
  856.     }
  857.  
  858.     switch (g_oppState)
  859.     {
  860.         case DEFENSIVE:
  861.         {                       
  862.             // Decide whether to move opponent backwards
  863.             if (r < 25)
  864.             {
  865.                 // Move the opponent backwards
  866.                 g_lpPlayer2->SetPosition(g_lpScene, player2pos.x, player2pos.y, player2pos.z + MOVE_NORMAL);
  867.                 
  868.                 // Play a walk sound
  869.                 PlaySoundDS(PLAYER2_WALK,player2pos);
  870.                 
  871.                 // Play a servo sound
  872.                 PlaySoundDS(SERVO_DOWN_3,player2pos);
  873.             }
  874.             PositionCamera();                   
  875.  
  876.             // Decide whether to go from DEFENSIVE to cautious
  877.             if (r < 10) g_oppState = CAUTIOUS;
  878.         }
  879.         break;
  880.  
  881.         case CAUTIOUS:
  882.         {
  883.             // Decide whether to go from CAUTIOUS to AGGRESSIVE
  884.             if (r < 5)
  885.             {
  886.                 // Make the opponent become aggresive
  887.                 g_oppState = AGGRESSIVE;
  888.             }
  889.         }
  890.         break;
  891.  
  892.         case AGGRESSIVE:
  893.         {                       
  894.             // Decide whether to move the opponent towards the player
  895.             if (r < 50)
  896.             {
  897.                 // Move the opponent towards the player
  898.                 if (curDist > MIN_DIST_TO_OPPONENT)
  899.                 {
  900.                     g_lpPlayer2->SetPosition(g_lpScene, player2pos.x, player2pos.y, player2pos.z - MOVE_NORMAL);
  901.                     PositionCamera();
  902.  
  903.                     // Play a walk sound
  904.                     PlaySoundDS(PLAYER2_WALK,player2pos);
  905.                     
  906.                     // Play a servo sound
  907.                     PlaySoundDS(SERVO_DOWN_3,player2pos);                          
  908.                 }
  909.             }
  910.  
  911.             // Decide whether or not to attack the player
  912.             if ((r < 15) && (g_player2State == BOBBING) && 
  913.                 (g_player1State != DEAD) && (curDist < MIN_DIST_TO_OPPONENT + D3DVAL(50)))
  914.             {
  915.                 // Set the opponent's state to PUNCHING
  916.                 g_player2State = PUNCHING;
  917.                 g_player2AnimArgs.time = PUNCH_START;
  918.                 g_player2AnimArgs.lpAnimSet->SetTime(PUNCH_START);
  919.                 
  920.                 // Play a servo sound
  921.                 PlaySoundDS(SERVO_UP_2,player2pos);
  922.             }
  923.  
  924.             // Decide whether or not to move the opponent backwards out of the way if the player
  925.             // is punching
  926.             if ((g_player1State == PUNCHING) && (r > 50) && (g_player2State == BOBBING) && (curDist < MIN_DIST_TO_OPPONENT + 50))
  927.             {
  928.                 // Move the opponent out of the way, making sure its still in the arena
  929.                 if (player2pos.z < EDGE_RIGHT) 
  930.                 {
  931.                     g_lpPlayer2->SetPosition(g_lpScene, player2pos.x, player2pos.y, player2pos.z + D3DVAL(5));
  932.                     
  933.                     // Play a servo sound
  934.                     PlaySoundDS(SERVO_DOWN_3,player1pos);
  935.                 }
  936.             }
  937.         }
  938.         break;
  939.     }
  940. }
  941.  
  942. //----------------------------------------------------------------------
  943. // 
  944. // Function     : RunIntro()
  945. //
  946. // Purpose      : Moves camera along path
  947. //
  948. //----------------------------------------------------------------------
  949.  
  950. void RunIntro()
  951. {
  952.     static D3DVALUE time = D3DVAL(0.0f);
  953.         D3DVECTOR d3dvPos;                      // D3DVECTOR used for 3D position of sound
  954.         d3dvPos.x = D3DVAL(0);          // set the sound at (0,0,0)..
  955.         d3dvPos.y = D3DVAL(0);
  956.         d3dvPos.z = D3DVAL(0);
  957.  
  958.     // Play the intro sound
  959.     if (time == D3DVAL(0.0f))
  960.     {
  961.         PlaySoundDS(INTRO,d3dvPos);
  962.         PlaySoundDS(CROWD_LOOP,d3dvPos, DSBPLAY_LOOPING);
  963.                 SetTimer(NULL,NULL,10000,PlayRandomWave);
  964.     }
  965.     
  966.     // Foward the intro animation
  967.     time += D3DVAL(0.04);
  968.  
  969.     // Set the animation time
  970.     g_lpAnim->SetTime(time);
  971.     
  972.     // Always look at the origin of the g_lpScene frame
  973.     g_lpCamera->LookAt(g_lpTmp, g_lpScene, D3DRMCONSTRAIN_Z);
  974.     
  975.     // If time has exceeded 1.0 the intro is done, and we can start the demo
  976.     if (time >= D3DVAL(1.0f))
  977.     {
  978.         g_appState = PLAYING_DEMO;
  979.         g_lpAnim->Release();
  980.         g_lpAnim = NULL;
  981.         PositionCamera();
  982.     }
  983. }
  984.  
  985. //----------------------------------------------------------------------
  986. // 
  987. // Function     : PostionCamera()
  988. //
  989. // Purpose      : Positions camera based upon camera state
  990. //
  991. //----------------------------------------------------------------------
  992.  
  993. void PositionCamera()
  994. {       
  995.     D3DVECTOR player1pos;
  996.     D3DVECTOR player2pos;
  997.     D3DVECTOR camPos;
  998.  
  999.     // Don't position the camera if we are transitioning between camera views
  1000.     if (g_appState == BETWEEN_CAM_VIEWS) return;
  1001.  
  1002.     // Get the players positions
  1003.     g_lpPlayer1->GetPosition(g_lpScene, &player1pos);   
  1004.     g_lpPlayer2->GetPosition(g_lpScene, &player2pos);
  1005.  
  1006.     // Get the camera's position
  1007.     g_lpCamera->GetPosition(g_lpScene, &camPos);
  1008.  
  1009.     switch (g_camState)
  1010.     {
  1011.         case OVER_SHOULDER:
  1012.         {
  1013.             // Position the camera such that it looks over the shoulder of the player and
  1014.             // keeps the opponent in view
  1015.             g_lpCamera->SetPosition(g_lpScene, camPos.x, camPos.y, D3DVAL(player1pos.z) + MOVE_NORMAL - 300);                   
  1016.             g_lpCamera->LookAt(g_lpPlayer2, g_lpScene, D3DRMCONSTRAIN_Z);
  1017.             if (g_lpDs3dListener)
  1018.             {
  1019.                 // Set the listener position to where the camera is
  1020.                 g_lpDs3dListener->SetPosition(camPos.x, camPos.y, D3DVAL(player1pos.z) + MOVE_NORMAL - 300,DS3D_DEFERRED);
  1021.                 // Change listener's orientation vector
  1022.                 g_lpDs3dListener->SetOrientation(D3DVAL(0),D3DVAL(0),D3DVAL(1),D3DVAL(0),D3DVAL(1),D3DVAL(0),DS3D_DEFERRED);
  1023.             }
  1024.         }
  1025.         break;
  1026.  
  1027.         case BOTH_IN_VIEW:
  1028.         {
  1029.             // Position the camera such that it looks at both players all the time
  1030.  
  1031.             // Make midway point, this is what the camera will focus on
  1032.             D3DVECTOR vMidPoint;
  1033.             vMidPoint.x = 0.0f;
  1034.             vMidPoint.y = 0.0f;
  1035.             vMidPoint.z = (player1pos.z + player2pos.z) / D3DVAL(2);
  1036.             
  1037.             // Calculate vector that will keep both players in sight
  1038.             D3DVECTOR vNewCam;
  1039.             vNewCam.x = (float)abs((int)player2pos.z - (int)player1pos.z) + D3DVAL(300);
  1040.             vNewCam.y = camPos.y;
  1041.             vNewCam.z = vMidPoint.z;
  1042.  
  1043.             g_lpCamera->SetPosition(g_lpScene, vNewCam.x, vNewCam.y, vNewCam.z);
  1044.                             
  1045.             g_lpTmp->SetPosition(g_lpScene, vMidPoint.x, vMidPoint.y, vMidPoint.z);
  1046.             g_lpCamera->LookAt(g_lpTmp, g_lpScene, D3DRMCONSTRAIN_Z);
  1047.             if (g_lpDs3dListener)
  1048.             {
  1049.                 // Set the listener position to where the camera is
  1050.                 g_lpDs3dListener->SetPosition(vNewCam.x, vNewCam.y, vNewCam.z,DS3D_DEFERRED);
  1051.                 // Change listener's orientation vector
  1052.                 g_lpDs3dListener->SetOrientation(-D3DVAL(1),D3DVAL(0),D3DVAL(0),D3DVAL(0),D3DVAL(1),D3DVAL(0),DS3D_DEFERRED);
  1053.             }
  1054.         }
  1055.         break;
  1056.  
  1057.         case PILOT_VIEW:
  1058.         {                                               
  1059.             // Position the camera such that it looks through the eyes of the player
  1060.             // and fixes on the origin of the head frame of the opponent
  1061.  
  1062.             g_lpCamera->SetPosition(g_lpPlayer1HeadFrame, D3DVAL(0), D3DVAL(-10), D3DVAL(0));
  1063.             g_lpTmp->SetPosition(g_lpPlayer2HeadFrame, D3DVAL(0), D3DVAL(-10), D3DVAL(0));
  1064.             g_lpCamera->LookAt(g_lpTmp, g_lpScene, D3DRMCONSTRAIN_Z);
  1065.             if (g_lpDs3dListener)
  1066.             {
  1067.                 // Set the listener position to where the camera is
  1068.                 g_lpDs3dListener->SetPosition(player1pos.x, D3DVAL(0), player1pos.z,DS3D_DEFERRED);
  1069.                 // Change listener's orientation vector
  1070.                 g_lpDs3dListener->SetOrientation(D3DVAL(0),D3DVAL(0),D3DVAL(1),D3DVAL(0),D3DVAL(1),D3DVAL(0),DS3D_DEFERRED);
  1071.             }
  1072.         }
  1073.         break;
  1074.     }
  1075.         // Commit the changes to the listener's orientation and position..
  1076.         if (g_lpDs3dListener)
  1077.             g_lpDs3dListener->CommitDeferredSettings();
  1078. }
  1079.  
  1080. //----------------------------------------------------------------------
  1081. // 
  1082. // Function     : TransitionCamera()
  1083. //
  1084. // Purpose      : Positions camera based upon camera state
  1085. //
  1086. //----------------------------------------------------------------------
  1087.  
  1088. void TransitionCamera()
  1089. {
  1090.     static D3DVALUE time = D3DVAL(0.0f);
  1091.  
  1092.     // Forward the transition animation time
  1093.     time += D3DVAL(0.04);
  1094.  
  1095.     // Set the time for the transitional animation
  1096.     g_lpAnim->SetTime(time);
  1097.  
  1098.     // Look at the g_lpScene frame
  1099.     g_lpCamera->LookAt(g_lpTmp, g_lpScene, D3DRMCONSTRAIN_Z);
  1100.  
  1101.     // If the animation has ended, run the demo
  1102.     if (time >= D3DVAL(1.0f))
  1103.     {
  1104.         g_appState = PLAYING_DEMO;
  1105.         g_lpAnim->Release();
  1106.         g_lpAnim = NULL;
  1107.         time = D3DVAL(0);
  1108.         PositionCamera();               
  1109.     }
  1110.  
  1111.     // Update debris so any debris in the scene doesn't just sit there doing nothing
  1112.     UpdateDebris();
  1113. }
  1114.  
  1115. //----------------------------------------------------------------------
  1116. // 
  1117. // Function     : AddDebris()
  1118. //
  1119. // Purpose      : Adds some debris to the scene
  1120. //
  1121. //----------------------------------------------------------------------
  1122.  
  1123. void AddDebris(D3DVECTOR vOrg, D3DVECTOR vVel, LPDIRECT3DRMMESHBUILDER pDebris)
  1124. {
  1125.     // vOrg is the origin of the debris, find first open spot and add 5 bits of debris
  1126.     int count = 0;
  1127.  
  1128.     for (int i = 0; i < NUM_DEBRIS; i ++)
  1129.     {
  1130.         // Find some debris that is not in use yet
  1131.         if (!g_debris[i].m_bInUse)
  1132.         {
  1133.             // Add some debris 
  1134.             g_debris[i].m_pFrame->AddVisual(pDebris);
  1135.             g_debris[i].m_pFrame->SetPosition(g_lpScene, vOrg.x, vOrg.y, vOrg.z);
  1136.             g_debris[i].m_pFrame->SetRotation(g_lpScene, D3DVAL(0.5), D3DVAL(0.5), D3DVAL(0.5), D3DVAL(0.5));
  1137.             g_debris[i].m_life = 0;
  1138.  
  1139.             // Setup velocity and acceleration
  1140.             g_debris[i].m_vel.x = D3DVAL(-10 + (rand() % 20)) + vVel.x;
  1141.             g_debris[i].m_vel.y = D3DVAL(8) + D3DVAL(rand() % 10) + vVel.y;
  1142.             g_debris[i].m_vel.z = D3DVAL(-10 + (rand() % 20)) + vVel.z;
  1143.  
  1144.             g_debris[i].m_acc.x = D3DVAL(0);
  1145.             g_debris[i].m_acc.y = D3DVAL(-2);
  1146.             g_debris[i].m_acc.z = D3DVAL(0);                    
  1147.  
  1148.             // This piece of debris is now in use
  1149.             g_debris[i].m_bInUse = TRUE;
  1150.             g_debris[i].m_pMeshBuilder = pDebris;
  1151.             
  1152.             count ++;                   
  1153.         }
  1154.  
  1155.         // Return if we've added NUM_HIT_DEBRIS bits of debris
  1156.         if (count == NUM_HIT_DEBRIS) return;
  1157.     }   
  1158. }
  1159.  
  1160. //----------------------------------------------------------------------
  1161. // 
  1162. // Function     : UpdateDebris()
  1163. //
  1164. // Purpose      : Updates debris
  1165. //
  1166. //----------------------------------------------------------------------
  1167.  
  1168. void UpdateDebris()
  1169. {
  1170.     D3DVECTOR vPos;
  1171.  
  1172.     // Go through the array of debris and update any debris that is in use
  1173.  
  1174.     for (int i = 0; i < NUM_DEBRIS; i ++)
  1175.     {
  1176.         if (g_debris[i].m_bInUse)
  1177.         {
  1178.             // If the debris's life has not yet expired
  1179.             if (g_debris[i].m_life < DEBRIS_LIFE)
  1180.             {
  1181.                 // Move the debris
  1182.                 g_debris[i].m_pFrame->GetPosition(g_lpScene, &vPos);
  1183.                 
  1184.                 g_debris[i].m_vel.x += g_debris[i].m_acc.x;
  1185.                 g_debris[i].m_vel.y += g_debris[i].m_acc.y;
  1186.                 g_debris[i].m_vel.z += g_debris[i].m_acc.z;
  1187.  
  1188.                 vPos.x += g_debris[i].m_vel.x;
  1189.                 vPos.y += g_debris[i].m_vel.y;
  1190.                 vPos.z += g_debris[i].m_vel.z;
  1191.  
  1192.                 // Check to see whether the debris is below the floor
  1193.                 if (vPos.y < D3DVAL(-60))
  1194.                 {
  1195.                         // Bounce the debris
  1196.                         vPos.y = D3DVAL(-60);
  1197.                         g_debris[i].m_vel.y = -g_debris[i].m_vel.y / D3DVAL(1.5);
  1198.                 }
  1199.  
  1200.                 // Update the position of the debris
  1201.                 g_debris[i].m_pFrame->SetPosition(g_lpScene, vPos.x, vPos.y, vPos.z);
  1202.             }
  1203.             else
  1204.             {
  1205.                 // Remove the debris from the world
  1206.                 g_debris[i].m_pFrame->DeleteVisual(g_debris[i].m_pMeshBuilder);
  1207.                 g_debris[i].m_bInUse = FALSE;
  1208.             }
  1209.  
  1210.             // Age the debris
  1211.             g_debris[i].m_life ++;
  1212.         }
  1213.     }
  1214. }
  1215.  
  1216.