home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / Source / Chapter 13 / Game / Game.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-10-01  |  11.2 KB  |  348 lines

  1. //-----------------------------------------------------------------------------
  2. // Game.h implementation.
  3. // Refer to the Game.h interface for more details.
  4. //
  5. // Programming a Multiplayer First Person Shooter in DirectX
  6. // Copyright (c) 2004 Vaughan Young
  7. //-----------------------------------------------------------------------------
  8. #include "Main.h"
  9.  
  10. //-----------------------------------------------------------------------------
  11. // Globals
  12. //-----------------------------------------------------------------------------
  13. Game *g_game = NULL;
  14.  
  15. //-----------------------------------------------------------------------------
  16. // Game class constructor.
  17. //-----------------------------------------------------------------------------
  18. Game::Game() : State( STATE_GAME )
  19. {
  20.     // Store a pointer to the game state in a global variable for easy access.
  21.     g_game = this;
  22.  
  23.     // Invalidate the score board font.
  24.     m_scoreBoardFont = NULL;
  25.  
  26.     // Invalidate both the bullet manager and the player manager.
  27.     m_bulletManager = NULL;
  28.     m_playerManager = NULL;
  29.  
  30.     // Invalidate the in-game music sound.
  31.     m_music = NULL;
  32. }
  33.  
  34. //-----------------------------------------------------------------------------
  35. // Allows the game state to preform any pre-processing construction.
  36. //-----------------------------------------------------------------------------
  37. void Game::Load()
  38. {
  39.     // Hide the mouse cursor.
  40.     ShowCursor( false );
  41.  
  42.     // Load the crosshair material.
  43.     m_crosshair = g_engine->GetMaterialManager()->Add( "Crosshair.dds.txt", "./Assets/" );
  44.  
  45.     // Create the score board font.
  46.     m_scoreBoardFont = new Font( "Arial", 14, FW_BOLD );
  47.     m_scoreBoardNames[0] = 0;
  48.     m_scoreBoardFrags[0] = 0;
  49.     m_scoreBoardDeaths[0] = 0;
  50.  
  51.     // Create both the bullet manager and the player manager.
  52.     m_bulletManager = new BulletManager;
  53.     m_playerManager = new PlayerManager;
  54.  
  55.     // Load and play the in-game music.
  56.     m_music = new Sound( "./Assets/Sounds/music_loop.wav" );
  57.     m_music->Play( true );
  58. }
  59.  
  60. //-----------------------------------------------------------------------------
  61. // Allows the game state to preform any post-processing destruction.
  62. //-----------------------------------------------------------------------------
  63. void Game::Close()
  64. {
  65.     // Show the mouse cursor.
  66.     ShowCursor( true );
  67.  
  68.     // Terminate the session.
  69.     g_engine->GetNetwork()->Terminate();
  70.  
  71.     // Destroy the scene.
  72.     g_engine->GetSceneManager()->DestroyScene();
  73.  
  74.     // Destroy both the bullet manager and the player manager.
  75.     SAFE_DELETE( m_bulletManager );
  76.     SAFE_DELETE( m_playerManager );
  77.  
  78.     // Destroy the score board font.
  79.     SAFE_DELETE( m_scoreBoardFont );
  80.  
  81.     // Destroy the crosshair material.
  82.     g_engine->GetMaterialManager()->Remove( &m_crosshair );
  83.  
  84.     // Destroy the in-game music.
  85.     SAFE_DELETE( m_music );
  86. }
  87.  
  88. //-----------------------------------------------------------------------------
  89. // Returns the view setup details for the given frame.
  90. //-----------------------------------------------------------------------------
  91. void Game::RequestViewer( ViewerSetup *viewer )
  92. {
  93.     viewer->viewer = m_playerManager->GetViewingPlayer();
  94.     viewer->viewClearFlags = D3DCLEAR_ZBUFFER;
  95. }
  96.  
  97. //-----------------------------------------------------------------------------
  98. // Update the game state.
  99. //-----------------------------------------------------------------------------
  100. void Game::Update( float elapsed )
  101. {
  102.     // Allow the player to respawn by pressing the R key.
  103.     if( g_engine->GetInput()->GetKeyPress( DIK_R ) == true )
  104.     {
  105.         m_playerManager->GetLocalPlayer()->SetEnabled( false );
  106.         m_playerManager->SpawnLocalPlayer();
  107.     }
  108.  
  109.     // Update the bullet manager before the player manager. This will prevent
  110.     // bullets that are fired this frame from being processed this frame.
  111.     m_bulletManager->Update( elapsed );
  112.  
  113.     // Update the player manager.
  114.     m_playerManager->Update( elapsed );
  115.  
  116.     // Check if the user is holding down the tab key.
  117.     if( g_engine->GetInput()->GetKeyPress( DIK_TAB, true ) == true )
  118.     {
  119.         // Build the score board text.
  120.         sprintf( m_scoreBoardNames, "PLAYER\n" );
  121.         sprintf( m_scoreBoardFrags, "FRAGS\n" );
  122.         sprintf( m_scoreBoardDeaths, "DEATHS\n" );
  123.  
  124.         // Add each player's details to the score board.
  125.         PlayerObject *player = m_playerManager->GetNextPlayer( true );
  126.         while( player != NULL )
  127.         {
  128.             strcat( m_scoreBoardNames, player->GetName() );
  129.             strcat( m_scoreBoardNames, "\n" );
  130.  
  131.             sprintf( m_scoreBoardFrags, "%s%d", m_scoreBoardFrags, player->GetFrags() );
  132.             strcat( m_scoreBoardFrags, "\n" );
  133.  
  134.             sprintf( m_scoreBoardDeaths, "%s%d", m_scoreBoardDeaths, player->GetDeaths() );
  135.             strcat( m_scoreBoardDeaths, "\n" );
  136.  
  137.             player = m_playerManager->GetNextPlayer();
  138.         }
  139.     }
  140.  
  141.     // Check if the user wants to exit back to the menu.
  142.     if( g_engine->GetInput()->GetKeyPress( DIK_ESCAPE ) )
  143.         g_engine->ChangeState( STATE_MENU );
  144. }
  145.  
  146. //-----------------------------------------------------------------------------
  147. // Render the game state.
  148. //-----------------------------------------------------------------------------
  149. void Game::Render()
  150. {
  151.     // Ensure the scene is loaded.
  152.     if( g_engine->GetSceneManager()->IsLoaded() == false )
  153.         return;
  154.  
  155.     // If the user is holding down the tab key, then render the score board.
  156.     if( g_engine->GetInput()->GetKeyPress( DIK_TAB, true ) == true )
  157.     {
  158.         m_scoreBoardFont->Render( m_scoreBoardNames, 20, 100, 0xFFFF7700 );
  159.         m_scoreBoardFont->Render( m_scoreBoardFrags, 180, 100, 0xFFFF7700 );
  160.         m_scoreBoardFont->Render( m_scoreBoardDeaths, 260, 100, 0xFFFF7700 );
  161.     }
  162.  
  163.     // Draw the local player's crosshair in the centre of the screen.
  164.     g_engine->GetSprite()->Begin( D3DXSPRITE_ALPHABLEND );
  165.     g_engine->GetSprite()->Draw( m_crosshair->GetTexture(), NULL, NULL, &D3DXVECTOR3( g_engine->GetDisplayMode()->Width / 2.0f - 15.0f, g_engine->GetDisplayMode()->Height / 2.0f - 15.0f, 0.0f ), 0xFFFFFFFF );
  166.     g_engine->GetSprite()->End();
  167. }
  168.  
  169. //-----------------------------------------------------------------------------
  170. // Returns a pointer to the bullet manager.
  171. //-----------------------------------------------------------------------------
  172. BulletManager *Game::GetBulletManager()
  173. {
  174.     return m_bulletManager;
  175. }
  176.  
  177. //-----------------------------------------------------------------------------
  178. // Handles the game specific network messages. Called by the network object.
  179. //-----------------------------------------------------------------------------
  180. void Game::HandleNetworkMessage( ReceivedMessage *msg )
  181. {
  182.     // Process the received messaged based on its type.
  183.     switch( msg->msgid )
  184.     {
  185.         case MSGID_CREATE_PLAYER:
  186.         {
  187.             // Add the new player to the player manager and the scene.
  188.             PlayerObject *object = m_playerManager->AddPlayer( g_engine->GetNetwork()->GetPlayer( msg->dpnid ) );
  189.             g_engine->GetSceneManager()->AddObject( object );
  190.  
  191.             // Check if the new player is the host player.
  192.             if( object->GetID() == g_engine->GetNetwork()->GetHostID() )
  193.             {
  194.                 // Load the scene from the host player's selection.
  195.                 g_engine->GetSceneManager()->LoadScene( ( (PlayerData*)g_engine->GetNetwork()->GetPlayer( msg->dpnid )->data )->map, "./Assets/Scenes/" );
  196.  
  197.                 // Allow the network to receive game specific messages.
  198.                 g_engine->GetNetwork()->SetReceiveAllowed( true );
  199.             }
  200.  
  201.             break;
  202.         }
  203.  
  204.         case MSGID_DESTROY_PLAYER:
  205.         {
  206.             // Remove the player from the player manager and the scene.
  207.             SceneObject *object = m_playerManager->GetPlayer( msg->dpnid );
  208.             g_engine->GetSceneManager()->RemoveObject( &object );
  209.             m_playerManager->RemovePlayer( msg->dpnid );
  210.  
  211.             break;
  212.         }
  213.  
  214.         case MSGID_PLAYER_HEALTH:
  215.         {
  216.             // Get a pointer to the game specific network message.
  217.             PlayerHealthMsg *phm = (PlayerHealthMsg*)msg;
  218.  
  219.             // Set the player's health.
  220.             m_playerManager->GetPlayer( phm->dpnid )->SetHealth( phm->health );
  221.  
  222.             // Check if the player has been killed.
  223.             if( phm->health <= 0.0f )
  224.                 m_playerManager->GetPlayer( phm->dpnid )->Kill();
  225.  
  226.             break;
  227.         }
  228.  
  229.         case MSGID_PLAYER_MOVE_UPDATE:
  230.         {
  231.             // Get a pointer to the game specific network message.
  232.             PlayerMoveUpdateMsg *pmum = (PlayerMoveUpdateMsg*)msg;
  233.  
  234.             // Get a pointer to the player in question.
  235.             PlayerObject *player = m_playerManager->GetPlayer( pmum->dpnid );
  236.  
  237.             // If the player is disabled then chances are the local player has
  238.             // just joined the game, and is receiving messages about a player
  239.             // that it does not realise has already spawned. So just enable
  240.             // that player and start updating it.
  241.             if( player->GetEnabled() == false )
  242.             {
  243.                 player->SetEnabled( true );
  244.                 player->SetVisible( true );
  245.             }
  246.  
  247.             // Update all the player's details.
  248.             player->SetTranslation( pmum->translation.x, pmum->translation.y, pmum->translation.z );
  249.             player->SetDrive( pmum->drive );
  250.             player->SetStrafe( pmum->strafe );
  251.             player->SetFire( pmum->fire );
  252.  
  253.             break;
  254.         }
  255.  
  256.         case MSGID_PLAYER_LOOK_UPDATE:
  257.         {
  258.             // Get a pointer to the game specific network message.
  259.             PlayerLookUpdateMsg *plum = (PlayerLookUpdateMsg*)msg;
  260.  
  261.             // Update the player's rotation and view tilt.
  262.             m_playerManager->GetPlayer( plum->dpnid )->SetRotation( 0.0f, plum->rotationY, 0.0f );
  263.             m_playerManager->GetPlayer( plum->dpnid )->SetViewTilt( plum->viewTilt );
  264.  
  265.             break;
  266.         }
  267.  
  268.         case MSGID_PLAYER_SCORE:
  269.         {
  270.             // Get a pointer to the game specific network message.
  271.             PlayerScoreMsg *psm = (PlayerScoreMsg*)msg;
  272.  
  273.             // Update the player's score.
  274.             m_playerManager->GetPlayer( psm->dpnid )->SetFrags( psm->frags );
  275.             m_playerManager->GetPlayer( psm->dpnid )->SetDeaths( psm->deaths );
  276.  
  277.             break;
  278.         }
  279.  
  280.         case MSGID_PLAYER_WEAPON_CHANGE:
  281.         {
  282.             // Get a pointer to the game specific network message.
  283.             PlayerWeaponChangeMsg *pwcm = (PlayerWeaponChangeMsg*)msg;
  284.  
  285.             // Change the player's weapon.
  286.             m_playerManager->GetPlayer( pwcm->dpnid )->WeaponChanged( pwcm->weapon );
  287.  
  288.             break;
  289.         }
  290.  
  291.         case MSGID_PLAYER_WEAPON_CHANGING:
  292.         {
  293.             // Get a pointer to the game specific network message.
  294.             PlayerWeaponChangeMsg *pwcm = (PlayerWeaponChangeMsg*)msg;
  295.  
  296.             // Indicate that this player is changing weapons.
  297.             m_playerManager->GetPlayer( pwcm->dpnid )->WeaponChanging();
  298.  
  299.             break;
  300.         }
  301.  
  302.         case MSGID_SPAWN_POINT_REQUEST:
  303.         {
  304.             // Send a spawn point message back to the requesting player.
  305.             SpawnPointMsg spm;
  306.             spm.msgid = MSGID_SPAWN_POINT;
  307.             spm.dpnid = msg->dpnid;
  308.             spm.spawnPoint = g_engine->GetSceneManager()->GetSpawnPointID( g_engine->GetSceneManager()->GetRandomPlayerSpawnPoint() );
  309.             g_engine->GetNetwork()->Send( &spm, sizeof( SpawnPointMsg ), msg->dpnid );
  310.  
  311.             break;
  312.         }
  313.  
  314.         case MSGID_SPAWN_POINT:
  315.         {
  316.             // Get a pointer to the game specific network message.
  317.             SpawnPointMsg *spm = (SpawnPointMsg*)msg;
  318.  
  319.             // Ensure this message is for the local player.
  320.             if( spm->dpnid != g_engine->GetNetwork()->GetLocalID() )
  321.                 break;
  322.  
  323.             // Spawn the local player using this spawn point.
  324.             m_playerManager->SpawnLocalPlayer( spm->spawnPoint );
  325.  
  326.             break;
  327.         }
  328.  
  329.         case MSGID_SPAWN_PLAYER:
  330.         {
  331.             // Get a pointer to the game specific network message.
  332.             SpawnPlayerMsg *spm = (SpawnPlayerMsg*)msg;
  333.  
  334.             // Spawn the player.
  335.             m_playerManager->SpawnPlayer( spm->dpnid, spm->translation );
  336.  
  337.             break;
  338.         }
  339.  
  340.         case MSGID_TERMINATE_SESSION:
  341.         {
  342.             // Switch to the menu state.
  343.             g_engine->ChangeState( STATE_MENU );
  344.  
  345.             break;
  346.         }
  347.     }
  348. }