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

📄 actionmap.cpp

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

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

// 包含Direct3D头文件
#include <d3d8.h>
#include <d3dx8.h>
#include <dinput.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

LPDIRECTINPUT8       g_pDI       = NULL;         

// 定义游戏主角的动作数据结构,有动作输入时,设置游戏主角的动作状态,
// 游戏主角根据自己的动作状态作出相应的反应。
typedef struct _PLAYERDATA {
    BOOL  bTurningRight;
    BOOL  bTurningLeft;
    BOOL  bForward;
    BOOL  bBackward;
    DWORD dwLRAxisData;
    DWORD dwUDAxisData;
	BOOL  bQuidGame;
} PLAYERDATA, *LPPLAYERDATA;

PLAYERDATA g_stPlayer;

// 使用输入设备数组  
#define MAX_DEVICES 25 
LPDIRECTINPUTDEVICE8 g_ppdidDevices[MAX_DEVICES];

// 读取输入设备输入数据包的数量
#define BUFFER_SIZE  16 

// 定义输入动作
#define INPUT_LEFTRIGHT_A      1L
#define INPUT_UPDOWN_A         2L
#define INPUT_TURNLEFT_B       3L
#define INPUT_TURNRIGHT_B      4L
#define INPUT_FORWARD_B        5L
#define INPUT_BACKWARD_B           6L
#define INPUT_QUITGAME_B         7L

// 定义动作映射表
#define NUMBER_OF_ACTIONS 9

DIACTION g_stGameAction[NUMBER_OF_ACTIONS] =
{
    // 其他输入设备,比如游戏杆等预先根据游戏类型定义了虚拟输入键
    // 我们根据选择的游戏类型来确定虚拟输入键和动作之间的映射
    { INPUT_LEFTRIGHT_A,  DIAXIS_SPACESIM_LATERAL,         0, _T("Turn"), },
    { INPUT_UPDOWN_A,     DIAXIS_SPACESIM_MOVE,            0, _T("Move"), },

    // 键盘的输入和动作之间的映射
    { INPUT_TURNLEFT_B,       DIKEYBOARD_LEFT,    0, _T("Turn left"), },
    { INPUT_TURNRIGHT_B,      DIKEYBOARD_RIGHT,   0, _T("Turn right"), },
    { INPUT_FORWARD_B,        DIKEYBOARD_UP,      0, _T("Forward thrust"), },
    { INPUT_BACKWARD_B,       DIKEYBOARD_DOWN,    0, _T("Reverse thrust"), },
    { INPUT_QUITGAME_B,       DIKEYBOARD_ESCAPE,  DIA_APPFIXED, _T("Quit Game"), },

    // 鼠标的输入和动作之间的映射
    { INPUT_LEFTRIGHT_A,  DIMOUSE_XAXIS,      0, _T("Turn"), },
    { INPUT_UPDOWN_A,     DIMOUSE_YAXIS,      0, _T("Move"), },
};

DIACTIONFORMAT g_diaf;
TCHAR*         g_szUserNames;
GUID           g_AppGuid    = { 0x451F8DEF, 0xA7E9, 0x4DF4, 0x9A, 0x6B,
                                      0xF4, 0xb6,0xC7, 0x06, 0xF3, 0x98 };

//-----------------------------------------------------------------------------
// 名称: ActionEnumDevices()
// 功能: 回调函数。
//       
//-----------------------------------------------------------------------------
BOOL CALLBACK ActionEnumDevices( LPCDIDEVICEINSTANCE  pdidi,
                            LPDIRECTINPUTDEVICE8 pdidDevice, 
							DWORD  dwFlags,
							DWORD  dwRemainingDevices,
							LPVOID pContext )
{
    HRESULT hr;

	HWND hWnd = (HWND)pContext;
	
	if( DI8DEVTYPE_DEVICECTRL == GET_DIDEVICE_TYPE(pdidi->dwDevType) )
    {
        return DIENUM_CONTINUE;     
    }

	// 设置设备的协作水平为独占方式和前台操作方式
	hr = pdidDevice->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );

    if( hr == DIERR_UNSUPPORTED )
    {
        MessageBox( hWnd, _T("SetCooperativeLevel() 不支持的协作模式\n"), 
						  _T("ActionMap"), MB_OK );
        return S_OK;
    }

	if( FAILED(hr) )
    {
        return DIENUM_CONTINUE;     
    }

	// 建立设备相关的动作映射结构
	hr = pdidDevice->BuildActionMap( &g_diaf, NULL, DIDSAM_DEFAULT );

	// 把动作映射表中该设备支持的动作映射设置到DirectInput设备中
	hr = pdidDevice->SetActionMap( &g_diaf, NULL, DIDSAM_DEFAULT ); 

	// 加入设置失败,继续进行枚举
	if( FAILED(hr) )
	{
	    return DIENUM_CONTINUE;
	}
    // 对于专用的游戏输入设备,设置Deadzone
    if(GET_DIDEVICE_TYPE(pdidi->dwDevType) & (~(DI8DEVTYPE_MOUSE & DI8DEVTYPE_KEYBOARD)))
    {
        DIPROPDWORD dipdw;
        dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
        dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
        dipdw.diph.dwObj        = 0;
        dipdw.diph.dwHow        = DIPH_DEVICE;
        dipdw.dwData            = 1000;

		pdidDevice->SetProperty( DIPROP_DEADZONE, &dipdw.diph );
    }

	// 把设置的设备加入到设备数组中
	DWORD iDev = 0;
    while( NULL != g_ppdidDevices[iDev] ) iDev++;

    g_ppdidDevices[iDev] = pdidDevice;
    g_ppdidDevices[iDev]->AddRef();
	
	return DIENUM_CONTINUE;
}



//-----------------------------------------------------------------------------
// 名称: ActionCreate()
// 功能: 创建动作映射。
//       
//-----------------------------------------------------------------------------
HRESULT ActionCreate( HWND hWnd)
{
	HRESULT hr;      

    // 创建DirectInput对象
    if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
                                         IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
        return hr;
    
	// 对设备数组清零操作
    ZeroMemory( g_ppdidDevices, sizeof(g_ppdidDevices) );

	g_diaf.dwSize        = sizeof(DIACTIONFORMAT);
	g_diaf.dwActionSize  = sizeof(DIACTION);
	g_diaf.dwDataSize    = NUMBER_OF_ACTIONS * sizeof(DWORD);
	g_diaf.dwNumActions  = NUMBER_OF_ACTIONS;
	g_diaf.guidActionMap = g_AppGuid;
	g_diaf.dwGenre       = DIVIRTUAL_SPACESIM;
	g_diaf.rgoAction     = g_stGameAction;
	g_diaf.dwBufferSize  = BUFFER_SIZE;
	g_diaf.lAxisMin      = -100;
	g_diaf.lAxisMax      = 100;
	_tcscpy( g_diaf.tszActionMap, _T("ActionMap Sample Application") );

	g_szUserNames  = _T("Player 1\0\0");

	hr = g_pDI->EnumDevicesBySemantics(g_szUserNames, &g_diaf, 
                                ActionEnumDevices, hWnd, DIEDBSFL_THISUSER | DIEDBSFL_AVAILABLEDEVICES);

	return S_OK;
}


//-----------------------------------------------------------------------------
// 名称: ActionFree()
// 功能: 释放设备。
//       
//-----------------------------------------------------------------------------
VOID ActionFree()
{
	DWORD dwD = 0;

    while( g_ppdidDevices[dwD] )
    {     
		g_ppdidDevices[dwD]->Unacquire();
		
        g_ppdidDevices[dwD]->SetActionMap( &g_diaf, NULL, DIDSAM_NOUSER );
        
        g_ppdidDevices[dwD]->Release();
        g_ppdidDevices[dwD] = NULL;
        dwD++;
    }

    SAFE_RELEASE( g_pDI );
}


//-----------------------------------------------------------------------------
// 名称: ActionRead(HWND hWnd)
// 功能: 读取设备的输入数据。
//       
//-----------------------------------------------------------------------------
BOOL ActionRead(HWND hWnd)
{
    HRESULT hr;
    DWORD   dwItems;
    DIDEVICEOBJECTDATA adod[BUFFER_SIZE];

    DWORD   dwDevice = 0;
    while ( g_ppdidDevices[dwDevice] )
    {
		g_ppdidDevices[dwDevice]->Acquire();

        // 从输入设备读取输入数据
        dwItems = BUFFER_SIZE;
        hr = g_ppdidDevices[dwDevice]->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
                                                    adod, &dwItems, 0 );

		if( SUCCEEDED(hr) )
		{           
            // 读取输入缓冲区中的输入数据,每个输入数据是一个DIDEVICEOBJECTDATA
			// 结构,输入数据的数量在dwItems中保存。在每个DIDEVICEOBJECTDATA结构
			// 中,uAppData成员表示输入数据代表的动作类型。实际数据在dwData中。
			for( DWORD j=0; j<dwItems; j++ )
			{
				// 对于按键数据,根据dwData判断是“按下”状态还是“未按下”状态
				// bState为真表示按键按下,为假表示按键释放
				BOOL bState = (adod[j].dwData != 0 ) ? TRUE : FALSE;

            	switch (adod[j].uAppData)
				{
				case INPUT_LEFTRIGHT_A: // Parse the left-right axis data
					g_stPlayer.dwLRAxisData  = adod[j].dwData;
					g_stPlayer.bTurningRight = g_stPlayer.bTurningLeft  = FALSE;					
					if( (int)g_stPlayer.dwLRAxisData > 0 )
						g_stPlayer.bTurningRight = TRUE;
					else if( (int)g_stPlayer.dwLRAxisData < 0 )
						g_stPlayer.bTurningLeft = TRUE;
                    break;

				case INPUT_UPDOWN_A: // Parse the up-down axis data
					g_stPlayer.dwUDAxisData   = adod[j].dwData;
					g_stPlayer.bBackward = g_stPlayer.bForward  = FALSE;	
					
					if( (int)g_stPlayer.dwUDAxisData > 0 )
						g_stPlayer.bBackward = TRUE;
					else if( (int)g_stPlayer.dwUDAxisData < 0 )
						g_stPlayer.bForward = TRUE;
					break;
					
				case INPUT_TURNLEFT_B:        
					g_stPlayer.bTurningLeft  = bState; break;

				case INPUT_TURNRIGHT_B:       
					g_stPlayer.bTurningRight = bState; break;

				case INPUT_FORWARD_B:   
					g_stPlayer.bForward  = bState; break;

				case INPUT_BACKWARD_B:   
					g_stPlayer.bBackward = bState; break;
		
                case INPUT_QUITGAME_B:       
					return FALSE;				
				

                }
			}
        }

        dwDevice++;
   	}

	return TRUE;
}

//-----------------------------------------------------------------------------
// 名称: PlayerProc()
// 功能: 处理游戏主角
//       
//-----------------------------------------------------------------------------
HRESULT PlayerProc()
{

	// 判断输入的方向
	if (g_stPlayer.bTurningRight)

⌨️ 快捷键说明

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