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

📄 client.cpp

📁 是《3D游戏编程》的代码 买了这本书
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// 名称: RenderSene.cpp
// 
// 功能: 进行3D场景的渲染——使用显示内存的顶点缓冲区。
//       
//-----------------------------------------------------------------------------

#include <tchar.h>
#include <windows.h>
#include <basetsd.h>
#include <objbase.h>

// 包含Direct3D头文件
#include <d3d8.h>
#include <d3dx8.h>
#include <dinput.h>
#include <dplay8.h>
#include <dpaddr.h>
#include <dxerr8.h>
#include <dpaddr.h>

// Windows类的名称宏定义
#define  MY_WINCLASS_NAME      "Direct3D"

struct PLAYER
{
    D3DXVECTOR3    LookAt[3];
};

// 定义个表示顶点的结构
struct CUSTOMVERTEX
{
    FLOAT x, y, z; // x,y,z表示点的三维坐标值,
    DWORD color;        // 顶点颜色
};

// 自定义的顶点格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

// 定义全局变量
LPDIRECT3D8             g_pMyD3D          = NULL; // 定义Direct3D对象的指针
LPDIRECT3DDEVICE8       g_pMyd3dDevice    = NULL; // 定义Direct3D设备指针
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferRec     = NULL; // 定义顶点缓冲区对象指针
LPDIRECT3DVERTEXBUFFER8 g_pMyVxBufferLine     = NULL;

PLAYER  g_Player;
float   g_Angle = 0;

#define LINE_VECTOR_NUM 20

// 定义包含4个顶点的顶点数组
CUSTOMVERTEX g_Vertices[] =
{
        { -1.5f, 0.0f, 0.0f, 0xffff0000, },  
        { -1.5f, 2.0f, 0.0f, 0xffff0000, },
		{  1.5f, 0.0f, 0.0f, 0xffff0000, },
		{  1.5f, 2.0f, 0.0f, 0xffff0000, },  

};
#define GRID_WIDTH       20.0f
#define NUM_GRID         20


#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#define SAMPLE_BUFFER_SIZE 8
#define TIME2FRAME 15

#define KEYDOWN(name, key) (name[key] & 0x80)

LPDIRECTINPUT8       g_pDI       = NULL;         
LPDIRECTINPUTDEVICE8 g_pKeyboard = NULL;     

IDirectPlay8Client* g_pDPClient  = NULL;
DWORD              g_dwPort;
GUID g_guidApp = { 0xede9493e, 0x6ac8, 0x4f15, { 0x8d, 0x1, 0x8b, 0x16, 0x32, 0x0, 0xb9, 0x66 } };

struct APP_PLAYER_INFO
{
    LONG  lRefCount;                        // Ref count so we can cleanup when all threads 
                                            // are done w/ this object
    DPNID dpnidPlayer;                      // DPNID of player
    TCHAR strPlayerName[20];   // Player name
};

#define GAME_MSGID_MESSAGE          1
#define GAME_MSGID_CREATE_PLAYER    2
#define GAME_MSGID_DESTROY_PLAYER   3
#define GAME_MSGID_SET_ID           4

struct GAMEMSG_GENERIC
{
	DWORD dwType;
    char  buffer[256];
};


struct DPHostInfo
{
    DWORD                 dwRef;
    DPN_APPLICATION_DESC* pAppDesc;
    IDirectPlay8Address* pHostAddr;
    IDirectPlay8Address* pDeviceAddr;
    TCHAR                szSession[MAX_PATH];
    DWORD                dwLastPollTime;
    BOOL                 bValid;
};

struct DPHostInfo *g_pDPHostInfo = new DPHostInfo;

//-----------------------------------------------------------------------------
// 名称: NetClientSendData()
// 功能: 发送数据。
//       
//-----------------------------------------------------------------------------
HRESULT NetClientSendData( struct GAMEMSG_GENERIC *pData )
{
	DPN_BUFFER_DESC bufferDesc;
	bufferDesc.dwBufferSize = sizeof(struct GAMEMSG_GENERIC);
	bufferDesc.pBufferData  = (BYTE*) pData;
	
	DPNHANDLE hAsync;
	g_pDPClient->Send( &bufferDesc, 1, 0, NULL, &hAsync, 0 );
	return S_OK;
}

//-----------------------------------------------------------------------------
// 名称: NetHostEnumResponse()
// 功能: 处理枚举会话应答消息。
//       
//-----------------------------------------------------------------------------
HRESULT NetClientHostEnumResponse( PDPNMSG_ENUM_HOSTS_RESPONSE pEnumHostsResponseMsg )
{
    HRESULT hr = S_OK;

    DPHostInfo* pDPHostEnum          = g_pDPHostInfo;
    const DPN_APPLICATION_DESC* pResponseMsgAppDesc =
                            pEnumHostsResponseMsg->pApplicationDescription;

    ZeroMemory( pDPHostEnum, sizeof(DPHostInfo) );

    // Update the pDPHostEnum with new information
    TCHAR strName[MAX_PATH];
    if( pResponseMsgAppDesc->pwszSessionName )
    {
        wcscpy( (unsigned short *)strName, pResponseMsgAppDesc->pwszSessionName );
    }


    //
    // Duplicate pEnumHostsResponseMsg->pAddressSender in pDPHostEnum->pHostAddr.
    // Duplicate pEnumHostsResponseMsg->pAddressDevice in pDPHostEnum->pDeviceAddr.
    //
    if( FAILED( hr = pEnumHostsResponseMsg->pAddressSender->Duplicate( &pDPHostEnum->pHostAddr ) ) )
    {
        DXTRACE_ERR( TEXT("Duplicate"), hr );
        goto LCleanup;
    }

    if( FAILED( hr = pEnumHostsResponseMsg->pAddressDevice->Duplicate( &pDPHostEnum->pDeviceAddr ) ) )
    {
        DXTRACE_ERR( TEXT("Duplicate"), hr );
        goto LCleanup;
    }

    // Deep copy the DPN_APPLICATION_DESC from
    pDPHostEnum->pAppDesc = new DPN_APPLICATION_DESC;
    ZeroMemory( pDPHostEnum->pAppDesc, sizeof(DPN_APPLICATION_DESC) );
    memcpy( pDPHostEnum->pAppDesc, pResponseMsgAppDesc, sizeof(DPN_APPLICATION_DESC) );
    if( pResponseMsgAppDesc->pwszSessionName )
    {
        pDPHostEnum->pAppDesc->pwszSessionName = new WCHAR[ wcslen(pResponseMsgAppDesc->pwszSessionName)+1 ];
        wcscpy( pDPHostEnum->pAppDesc->pwszSessionName,
                pResponseMsgAppDesc->pwszSessionName );
    }

    // Update the time this was done, so that we can expire this host
    // if it doesn't refresh w/in a certain amount of time
    pDPHostEnum->dwLastPollTime = timeGetTime();

    // Check to see if the current number of players changed
    TCHAR szSessionTemp[MAX_PATH];
    if( pResponseMsgAppDesc->dwMaxPlayers > 0 )
    {
        wsprintf( szSessionTemp, TEXT("%s (%d/%d) (%dms)"), strName,
                  pResponseMsgAppDesc->dwCurrentPlayers - 1,  // ignore the host player
                  pResponseMsgAppDesc->dwMaxPlayers - 1,      // ignore the host player
                  pEnumHostsResponseMsg->dwRoundTripLatencyMS );
    }
    else
    {
        wsprintf( szSessionTemp, TEXT("%s (%d) (%dms)"), strName,
                  pResponseMsgAppDesc->dwCurrentPlayers - 1,  // ignore the host player
                  pEnumHostsResponseMsg->dwRoundTripLatencyMS );
    }

    _tcscpy( pDPHostEnum->szSession, szSessionTemp );

    // This host is now valid
    pDPHostEnum->bValid = TRUE;

LCleanup:

    return hr;
}


//-----------------------------------------------------------------------------
// 名称: NetClientMessageHandler()
// 功能: 处理消息接收。
//       
//-----------------------------------------------------------------------------
HRESULT WINAPI NetClientMessageHandler( PVOID pvUserContext, 
                                         DWORD dwMessageId, 
                                         PVOID pMsgBuffer )
{
   switch( dwMessageId )
    {
	    case DPN_MSGID_ENUM_HOSTS_RESPONSE:
        {
            PDPNMSG_ENUM_HOSTS_RESPONSE pEnumHostsResponseMsg;
            pEnumHostsResponseMsg = (PDPNMSG_ENUM_HOSTS_RESPONSE)pMsgBuffer;

            // Take note of the host response
            NetClientHostEnumResponse( pEnumHostsResponseMsg );
            break;
		}

        case DPN_MSGID_CREATE_PLAYER:
        {
            break;
        }

        case DPN_MSGID_DESTROY_PLAYER:
        {
            break;
        }

        case DPN_MSGID_TERMINATE_SESSION:
        {
            break;
        }

        case DPN_MSGID_RECEIVE:
        {
            PDPNMSG_RECEIVE pReceiveMsg;
            pReceiveMsg = (PDPNMSG_RECEIVE)pMsgBuffer;
            APP_PLAYER_INFO* pPlayerInfo = (APP_PLAYER_INFO*) pReceiveMsg->pvPlayerContext;

            GAMEMSG_GENERIC* pMsg = (GAMEMSG_GENERIC*) pReceiveMsg->pReceiveData;
			
			// 接收数据 
            
            break;
        }
    }

    return S_OK;
}

//-----------------------------------------------------------------------------
// 名称: NetSessionsEnumHosts()
// 功能: 枚举会话中的宿主。
//       
//-----------------------------------------------------------------------------
HRESULT NetClientEnumHosts( HWND hWnd )
{
    HRESULT hr;

    DPN_APPLICATION_DESC   dpnAppDesc;
    IDirectPlay8Address*   pDP8AddressHost  = NULL;
    IDirectPlay8Address*   pDP8AddressLocal = NULL;
    WCHAR*                 wszHostName      = NULL;
    DPNHANDLE               m_hEnumAsyncOp = NULL;

    // 设置服务器的IP地址
    TCHAR strIPAddress[MAX_PATH] = TEXT("127.0.0.1");

    // 创建本地地址对象
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, 
                                       CLSCTX_ALL, IID_IDirectPlay8Address,
                                       (LPVOID*) &pDP8AddressLocal ) ) )
    {
        DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
        goto LCleanup;
    }

    // 设置地址对象的网络协议为TCP/IP协议
    if( FAILED( hr = pDP8AddressLocal->SetSP( &CLSID_DP8SP_TCPIP ) ) )
    {
        DXTRACE_ERR( TEXT("SetSP"), hr );
        goto LCleanup;
    }


    // 创建服务器的地址对象
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, 
                                       CLSCTX_ALL, IID_IDirectPlay8Address,
                                       (LPVOID*) &pDP8AddressHost ) ) )
    {
        DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
        goto LCleanup;
    }

    // 设置地址对象的网络协议为TCP/IP协议
    if( FAILED( hr = pDP8AddressHost->SetSP( &CLSID_DP8SP_TCPIP ) ) )
    {
        DXTRACE_ERR( TEXT("SetSP"), hr );
        goto LCleanup;
    }

    if( strIPAddress != NULL && strIPAddress[0] != 0 )
    {
        DWORD dwPort = 0;

        wszHostName = new WCHAR[_tcslen(strIPAddress)+1];

		int cchDestChar;		        
		cchDestChar = strlen(strIPAddress)+1;  
		MultiByteToWideChar( CP_ACP, 0, strIPAddress, -1, 
                         wszHostName, cchDestChar-1 );
		wszHostName[cchDestChar-1] = 0;

        hr = pDP8AddressHost->AddComponent( DPNA_KEY_HOSTNAME, wszHostName, 
                                            (wcslen(wszHostName)+1)*sizeof(WCHAR), 
                                            DPNA_DATATYPE_STRING );
        if( FAILED(hr) )
        {
            DXTRACE_ERR( TEXT("AddComponent"), hr );
            goto LCleanup;
        }

        // If a port was specified in the IP string, then add it.
        // Games will typically hard code the port so the user need not know it
        if( dwPort != 0 )
        {
            hr = pDP8AddressHost->AddComponent( DPNA_KEY_PORT, 
                                                &dwPort, sizeof(dwPort),
                                                DPNA_DATATYPE_DWORD );
            if( FAILED(hr) )
            {
                DXTRACE_ERR( TEXT("AddComponent"), hr );
                goto LCleanup;
            }
        }
    }

    ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );
    dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
    dpnAppDesc.guidApplication = g_guidApp;

    // 枚举会话宿主
    hr = g_pDPClient->EnumHosts( &dpnAppDesc, pDP8AddressHost, 
                                 pDP8AddressLocal, NULL, 
                                 0, 0, 0, 0, NULL, 
                                 NULL, DPNENUMHOSTS_SYNC  );
    if( FAILED(hr) )
    {
        if( hr != DPNERR_INVALIDDEVICEADDRESS && 
            hr != DPNERR_ADDRESSING ) 
            DXTRACE_ERR( TEXT("EnumHosts"), hr );
        goto LCleanup;
    }

LCleanup:
    SAFE_RELEASE( pDP8AddressHost);
    SAFE_RELEASE( pDP8AddressLocal );
    SAFE_DELETE( wszHostName );

    if( hr == DPNERR_PENDING )
        hr = DPN_OK;

    return hr;
}

//-----------------------------------------------------------------------------
// 名称: NetClientStart()
// 功能: 启动服务器。
//       
//-----------------------------------------------------------------------------
HRESULT NetClientStart( HWND hWnd )
{
    HRESULT hr;
    WCHAR wszPeerName[MAX_PATH];

    // 创建 IDirectPlay8Client
    if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Client, NULL, 
                                       CLSCTX_INPROC_SERVER,
                                       IID_IDirectPlay8Client, 
                                       (LPVOID*) &g_pDPClient ) ) )
        return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );


	// 初始化 IDirectPlay8Client
    if( FAILED( hr = g_pDPClient->Initialize( NULL, NetClientMessageHandler, 0 ) ) )
        return DXTRACE_ERR( TEXT("Initialize"), hr );


	if(FAILED(hr = NetClientEnumHosts(hWnd )))
		return DXTRACE_ERR( TEXT("EnumHost Err"), hr );

    DPN_PLAYER_INFO dpPlayerInfo;
    ZeroMemory( &dpPlayerInfo, sizeof(DPN_PLAYER_INFO) );
    dpPlayerInfo.dwSize = sizeof(DPN_PLAYER_INFO);
    dpPlayerInfo.dwInfoFlags = DPNINFO_NAME;
    dpPlayerInfo.pwszName = wszPeerName;

    // 设置本地游戏主机信息
    if( FAILED( hr = g_pDPClient->SetClientInfo( &dpPlayerInfo, NULL, NULL, DPNOP_SYNC ) ) )
        return DXTRACE_ERR( TEXT("SetPeerInfo"), hr );

    // 连接到会话中的服务器
    hr = g_pDPClient->Connect( g_pDPHostInfo->pAppDesc,       // the application desc
                               g_pDPHostInfo->pHostAddr,      // address of the host of the session
                               g_pDPHostInfo->pDeviceAddr,    // address of the local device the enum responses were received on
                               NULL, NULL,                          // DPN_SECURITY_DESC, DPN_SECURITY_CREDENTIALS
                               NULL, 0,                             // user data, user data size
                               NULL, NULL,            // async context, async handle,
                               DPNCONNECT_SYNC   ); // flags
    if( hr != E_PENDING && FAILED(hr) )
        return DXTRACE_ERR( TEXT("Connect"), hr );

	return S_OK;
}

//-----------------------------------------------------------------------------
// 名称: NetClientStop()
// 功能: 关闭会话。
//       
//-----------------------------------------------------------------------------
VOID NetClientStop( )
{
    if( g_pDPClient )
    {
        g_pDPClient->Close(0);
        SAFE_RELEASE( g_pDPClient );
    }

}



//-----------------------------------------------------------------------------
// 名称: FreeDirectInput()
// 功能: 释放键盘设备。
//       
//-----------------------------------------------------------------------------
VOID KeyboardFree()
{
    // 释放设备
    if( g_pKeyboard ) 
        g_pKeyboard->Unacquire();
    

⌨️ 快捷键说明

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