⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.cpp

📁 <B>DirectX9.0 3D游戏编程</B>
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************
 *         Advanced 3D Game Programming using DirectX 9.0
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * copyright (c) 2003 by Peter A Walsh and Adrian Perez
 * See license.txt for modification and distribution information
 ******************************************************************/

#include "stdafx.h"
	
#include "..\NetLib\cDataExtract.h"
#include "..\NetLib\cDataCompress.h"
#include "..\NetLib\cNetError.h"

#include "..\\gamecommon\\netmsgs\\LoginNM.h"
#include "..\\gamecommon\\netmsgs\\EntNM.h"

#include "..\\gamecommon\\viewcone.h"

#include <deque>
using namespace std;

void PlayGameSound( resID id )
{
	cSoundWrapper* pSoundWrap = (cSoundWrapper*)Resources()->Get( id );
	pSoundWrap->Play();
}

bool IsClient()
{
	return true;
}

objID g_pPlayerID = -1;

objID GetClientID()
{
	return g_pPlayerID;
}

int g_useTextures = 1;

////////////////////////////////////////////////////////////////////////////////

#define MAX_PLAYERS			8	// max players

#define SERVER_LISTENPORT	4000	// the port the server is listening for data on.
#define CLIENT_LISTENPORT	4001	// the port the client is listening for data on.

/**
 * Drawing code is divorced from everything else so that 
 * the server doesn't need to include any of the DirectX
 * headers (makes it smaller and faster)
 */
extern bool DrawCell( cGameCell* pCell );
extern bool DrawEnt( cGameEnt* pEnt );
extern void InitLights();

////////////////////////////////////////////////////////////////////////////////

class cGameApp 
: public cApplication
, public iKeyboardReceiver
, public iMouseReceiver
, public iGameObject
{
	// how long the last frame took (the next one should take about as long)
	float m_timeDelta;

	// the client's player
	objID			m_clientID;
	cGamePlayerEnt*	m_pPlayer;

	// The world
	cGameWorld* m_pWorld;

	deque<string> m_console;

	bool		m_bConnected; // We are actually able to play.

	int			m_numPlayers;
	string		m_IPAddress,	// If server, what address do we connect to?
				m_localPlayerName;	// The player's name, as specified on the command line.
	bool		m_bInverseMouse;	// Invert the mouse for those player who prefer it?
	MTUDP		m_comm;	// the network comm class
	HOSTHANDLE	m_serverHost;	// the handle to the server host.

	sEntState	m_desiredState;
	bool		m_bInputTaken;

	float		m_deltaYaw, m_deltaPitch;
	point3		m_deltaLoc;

	bool		m_bDrawScoreboard;

	virtual void InitInput()
	{
		// We need to grab exclusive access to the input devices.  This is 
		// for two reasons... one, when we're windowed we want to avoid 
		// having out-of-window clicks cause a loss of focus.  Second, 
		// under Win2K, there is a problem with DirectInput that causes
		// 'sticky' input devices if they're not grabbed exclusively.  
		// Two birds with one stone.
		cInputLayer::Create( 
			AppInstance(), MainWindow()->GetHWnd(), 
			true, true, true );
	}

public:
	virtual void InitExtraSubsystems()
	{
		new cResourceMgr("media\\level1.res");
		MsgDaemon()->RegObject( g_gameID, this );
	}

	void InitClient();

	void ClientFrame( float timeDelta );
	void RenderFrame( float timeDelta );

	void DrawConsole();
	void AddTextLine( const char* text );

	void DrawScoreBoard();

	void HandleInput();

	//==========--------------------------	cApplication

	virtual void Run();
	virtual void DoFrame( float timeDelta );
	virtual void SceneInit();
	virtual void SceneEnd();

	cGameApp() 
	: cApplication()
	, m_console( 10, string("") )
	{
		m_pWorld = NULL;
		m_title = string( "Mobots Attack!!" );
		m_pPlayer = NULL;

		m_numPlayers = 0;
		m_bInverseMouse = false;
		m_bDrawScoreboard = false;
	}


	~cGameApp()
	{
		delete m_pWorld;
		delete Resources();
	}

	//==========--------------------------	iKeyboardReceiver

	virtual void KeyUp( int key );
	virtual void KeyDown( int key );

	//==========--------------------------	iMouseReceiver

	virtual void MouseMoved( int dx, int dy );
	virtual void MouseButtonUp( int button );
	virtual void MouseButtonDown( int button );

	//==========--------------------------	iGameObject
	virtual objID GetID(){	return g_gameID; }
	virtual void SetID( objID id ){}
	virtual uint ProcMsg( const sMsg& msg );

	//==========--------------------------	

	void ParseCmdLine( char* cmdLine );

	//==========--------------------------	Network message parsing
	
	void MakeFireRequest();

	void SendToServerR( cNetMessage& nMsg );
	void SendToServerUR( cNetMessage& nMsg );
};
////////////////////////////////////////////////////////////////////////////////

cApplication* CreateApplication()
{
	return new cGameApp();
}

void cGameApp::SceneInit()
{
	LogPrint("Enter cGameApp::SceneInit()");
	Graphics()->SetProjectionData( PI/3, 0.1f, 40.0f );
	Graphics()->MakeProjectionMatrix();

	Input()->GetKeyboard()->SetReceiver( this );
	if( Input()->GetMouse() )
		Input()->GetMouse()->SetReceiver( this );

	// initialize our scene
	LPDIRECT3DDEVICE9 pDevice = Graphics()->GetDevice();
	pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
	pDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
	pDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE );
	pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
	pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

	pDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
	pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
	pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
	
	// Load the default world.
	cFile file;
	file.Open( "media\\level1.world" );
	m_pWorld = new cGameWorld( file );
	file.Close();

	Graphics()->SetWorldMatrix( matrix4::Identity );

	m_timeDelta = 0.03f; // a 30th of a second is a good first value

	InitClient();

	AddTextLine("[SceneInit]: Finished initializing\n");
}

void cGameApp::SceneEnd()
{
	/**
	 * Notify the server that we're outta here.
	 */
	if( m_pPlayer )
	{
		cNM_LogoutNotice msg( m_pPlayer->GetID() );
		SendToServerR( msg );
	}
}


void cGameApp::DoFrame( float timeDelta )
{
	// update the time
	m_timeDelta = timeDelta;

	// Our network thread has failed, abort now.
	if( m_comm.cThread::IsRunning() == false )
		throw cNetError( m_comm.cThread::Error() );

	ClientFrame( timeDelta );
	RenderFrame( timeDelta );

	m_comm.ResendPackets();


}



void cGameApp::KeyUp( int key )
{
	switch( key )
	{
	case DIK_TAB:
		m_bDrawScoreboard = false;
	}
}


void cGameApp::KeyDown( int key )
{
	if( !m_bConnected )
		return;

	m_pPlayer->RebuildMatrix();
	const matrix4 mat = m_pPlayer->GetMatrix();

	switch( key )
	{
	case DIK_GRAVE: // Clear the console
		{
			for( int i=0; i<10; i++ )
			{
				AddTextLine( "" );
			}
		}
		break;
		// fire rocket
	case DIK_LCONTROL:
		MakeFireRequest();
		break;

		// tilt up
	case DIK_PRIOR:
	case DIK_NUMPAD9:
		{
			m_deltaPitch += m_timeDelta * 1.8f;
			break;
		}
		
		// tilt down
	case DIK_NEXT:
	case DIK_NUMPAD3:
		{
			m_deltaPitch -= m_timeDelta * 1.8f;
			break;
		}

		// move forward
	case DIK_UP:
	case DIK_NUMPAD8:
		{
			point3 zAxis = mat.GetAxis(2);
			m_deltaLoc += (zAxis * 10.0f);
			break;
		}

		// move backward
	case DIK_DOWN:
	case DIK_NUMPAD2:
	case DIK_E:
		{
			point3 zAxis = mat.GetAxis(2);
			m_deltaLoc -= 10.0f * zAxis;
			break;
		}

		// strafe right
	case DIK_F:
		{
			point3 xAxis = mat.GetAxis(0);
			m_deltaLoc += 10.0f * xAxis;
			break;
		}

		// strafe left
	case DIK_S:
		{
			point3 xAxis = mat.GetAxis(0);
			m_deltaLoc -= 10.0f * xAxis;
			break;
		}

		// move up
	case DIK_SPACE:
		{
			point3 yAxis = mat.GetAxis(1);
			m_deltaLoc += 10.0f * yAxis;
			break;
		}

		// move down
	case DIK_D:
		{
			point3 yAxis = mat.GetAxis(1);
			m_deltaLoc -= 10.0f * yAxis;
			break;
		}

		// turn right
	case DIK_RIGHT:
	case DIK_NUMPAD6:
		{
			m_deltaYaw += m_timeDelta * 1.8f;
			break;
		}

		// turn left
	case DIK_LEFT:
	case DIK_NUMPAD4:
		{
			m_deltaYaw -= m_timeDelta * 1.8f;
			break;
		}

		// turn on scoreboard
	case DIK_TAB:
		m_bDrawScoreboard = true;
	}
}


void cGameApp::MouseMoved( int dx, int dy )
{
	if( !m_bConnected )
		return;

	m_deltaYaw += 0.01f * (float)dx;
	m_deltaPitch += 0.01f * (float)dy * ( m_bInverseMouse == true ? -1 : 1 );
	
}

void cGameApp::MouseButtonUp( int button )
{
	if( !m_bConnected )
		return;

	// If we're dead, try to respawn.
	if( m_pPlayer->GetStatus() == gesDead ||
		m_pPlayer->GetStatus() == gesUnSpawned )
	{
		cNM_SpawnReq msg( m_pPlayer->GetID() );
		SendToServerR( msg );
	}
}

void cGameApp::MouseButtonDown( int button )
{
	if( !m_bConnected )
		return;

	if( button == 0 )
		MakeFireRequest();

	if( button == 1 )
	{
		m_bInputTaken = true;
		matrix4 mat = m_desiredState.BuildMatrix();
	
		point3 zAxis = mat.GetAxis(2);

		m_deltaLoc += 10.0f * zAxis;
	}
}


void cGameApp::Run()
{
	bool done = false;

	static float lastTime = (float)timeGetTime(); 

	while( !done )
	{
		if( Input()->GetKeyboard()->Poll( DIK_ESCAPE ) ||
			Input()->GetKeyboard()->Poll( DIK_Q ) )
		{
			PostMessage( MainWindow()->GetHWnd(), WM_CLOSE, 0, 0 );
		}

		while( !done && MainWindow()->HasMessages() )
		{
			if( resFalse == MainWindow()->Pump() )
				done = true;
		}

		float currTime = (float)timeGetTime();
		float delta = (currTime - lastTime)/1000.f;

		if( m_bActive )
		{
			DoFrame( delta );
		}
		else
		{
			DoIdleFrame( delta );
		}

		lastTime = currTime;
	}
}



void cGameApp::InitClient()
{

	/**
	 * Initially, we are not connected to the game
	 */
	m_bConnected = false;

	
	/* Player name is given in the command line, or read from the init file, 
	 * so we should have it.
	 * do any housekeeping, set up our sockets, and request a connection with the server.
	 * print some sort of ghetto "connecting" message on the screen.
	 */
	m_comm.Startup( CLIENT_LISTENPORT, SERVER_LISTENPORT );
	m_comm.StartClient();

	/**
	 * Client side I open a listening socket first so that I will not
	 * be able to send any data without being ready to read data.
	 * Internally to MTUDP it makes no difference.
	 */
	m_comm.StartListening();
	m_comm.StartSending();

	/**
	 * Open a connection to the server
	 */
	m_serverHost = m_comm.HostCreate( (char*)m_IPAddress.c_str(), SERVER_LISTENPORT );

	/**
	 * Attempt to log the player in.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -