📄 actionmap.cpp
字号:
//-----------------------------------------------------------------------------
// 名称: 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 + -