本来按照Programming.Role.Playing.Games.with.DirectX书上的节奏,接下来的应该是公告牌的内容,用shader也实现了效果,但得到的效果是图形是有点旋转的,其他都没问题,这就尴尬了,找了大佬看了下,大佬也说shader代码怎么看都没问题,需要调试才能找问题,dx9调试就有点麻烦就懒得弄,直接跳过了。
后面的粒子特效也是使用了公告牌的,所以也跳过。所以想了下,剩下的内容就等什么时候再来仔细看下。就直接跳到下一章节,DirectInput输入。书上内容有点多,还分了好几个代码工程,嫌麻烦,就整合在一个工程里。用了之前写的Font工程,所以就跟书上的代码不一样,直接用DirectX的Font来显示信息。
左上角的就是枚举所有设备,中间MousePos就是根据鼠标设备移动计算出来的,按下Esc键会弹出MessageBox询问是否需要关闭是根据键盘设备实现的。尴尬的是Joystick,我用了PS4和PS3设备都没有找到Joystick设备,用了InputMapper就变成了鼠标设备了,真是见鬼了,所以就没有测试过Joystick的代码。
这里讲下判断按键是否按下的计算,函数是这样的:
bool InputClass::IsKeyDown(int key)
{
return m_keyboardState[key] & 0x80;
}
其实这是一个很简单的位运算,书上讲最高位存储的0和1其实就是判断按键是否按下,0是未按下,1是按下。而0x80的2进制是10000000,因此m_keyboardState[key]的前7位进行按位与运算后,得出的值是0000000,因此看最高位的运算,如果按下最高位为1,按位与后得出的值为10000000,也就是0x80,返回值就为true,表示被按下。如果未按下,最高位为0,按位与后得出的值为00000000,也就是0,返回值就为false,表示未按下。
因为没什么shader代码,而且DirectInput网上有很多详细的介绍,比自己边查字典边看Programming.Role.Playing.Games.with.DirectX更加好,也就不多说了,直接上代码:核心就是创建设备(CreateDevice),设置协作级(SetCooperativeLevel),设置数据格式(SetDataFormat),然后获取(Acquire)
#define DIRECTINPUT_VERSION 0x800
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#include <dinput.h>
class InputClass
{
public:
InputClass();
InputClass(const InputClass& other);
~InputClass();
bool Initialize(HINSTANCE hInstance, HWND hwnd);
void Shutdown();
bool Frame();
void EnumDevices(LPDIENUMDEVICESCALLBACKW callback, LPVOID ptrPara);
bool IsKeyDown(int key);
void GetMousePosition(int& mouseX, int& mouseY);
void GetJoystickPosition(int& joystickX, int& joystickY);
private:
bool InitializeKeyboard();
bool ReadKeyboard();
bool InitializeMouse();
bool ReadMouse();
void ProcessMouse();
bool InitializeJoystick();
static bool CALLBACK EnumJoysticks(LPCDIDEVICEINSTANCE instance, LPVOID ptrParam);
bool ReadJoystick();
private:
IDirectInput8* m_input;
HWND m_hwnd;
IDirectInputDevice8* m_keyboard;
unsigned char m_keyboardState[256];
IDirectInputDevice8* m_mouse;
DIMOUSESTATE m_mouseState;
int m_mouseX, m_mouseY;
IDirectInputDevice8* m_joystick;
DIJOYSTATE m_joystickState;
};
实现:
#include "InputClass.h"
InputClass::InputClass()
{
m_input = nullptr;
m_keyboard = nullptr;
m_mouse = nullptr;
m_joystick = nullptr;
}
InputClass::InputClass(const InputClass& other)
{
}
InputClass::~InputClass()
{
}
bool InputClass::Initialize(HINSTANCE hInstance, HWND hwnd)
{
HRESULT hResult;
bool result;
hResult = ::DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_input, nullptr);
if (FAILED(hResult))
return false;
m_hwnd = hwnd;
result = InitializeKeyboard();
if (!result)
return false;
result = InitializeMouse();
if (!result)
return false;
result = InitializeJoystick();
if (!result)
::MessageBox(nullptr, TEXT("InitializeJoystick - Failed"), TEXT("Error"), MB_OK | MB_ICONERROR);
return true;
}
void InputClass::Shutdown()
{
if (m_keyboard)
{
m_keyboard->Unacquire();
m_keyboard->Release();
m_keyboard = nullptr;
}
if (m_mouse)
{
m_mouse->Unacquire();
m_mouse->Release();
m_mouse = nullptr;
}
if (m_joystick)
{
m_joystick->Unacquire();
m_joystick->Release();
m_joystick = nullptr;
}
if (m_input)
{
m_input->Release();
m_input = nullptr;
}
}
bool InputClass::Frame()
{
bool result;
result = ReadKeyboard();
if (!result)
return false;
result = ReadMouse();
if (!result)
return false;
ProcessMouse();
result = ReadJoystick();
if (!result)
return false;
return true;
}
void InputClass::EnumDevices(LPDIENUMDEVICESCALLBACKW callback, LPVOID ptrPara)
{
m_input->EnumDevices(DI8DEVCLASS_ALL, callback, ptrPara, DIEDFL_ALLDEVICES);
}
bool InputClass::IsKeyDown(int key)
{
return m_keyboardState[key] & 0x80;
}
void InputClass::GetMousePosition(int& mouseX, int& mouseY)
{
mouseX = m_mouseX;
mouseY = m_mouseY;
}
bool InputClass::InitializeKeyboard()
{
HRESULT result;
result = m_input->CreateDevice(GUID_SysKeyboard, &m_keyboard, nullptr);
if (FAILED(result))
return false;
result = m_keyboard->SetDataFormat(&c_dfDIKeyboard);
if (FAILED(result))
return false;
result = m_keyboard->SetCooperativeLevel(m_hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(result))
return false;
result = m_keyboard->Acquire();
if (FAILED(result))
return false;
return true;
}
bool InputClass::ReadKeyboard()
{
HRESULT result;
result = m_keyboard->Poll();
if (FAILED(result))
return false;
result = m_keyboard->GetDeviceState(sizeof(m_keyboardState), (LPVOID)&m_keyboardState);
if (FAILED(result))
{
if (DIERR_INPUTLOST == result || DIERR_NOTACQUIRED == result)
{
result = m_keyboard->Acquire();
if (FAILED(result))
return false;
}
else
return false;
}
return true;
}
bool InputClass::InitializeMouse()
{
HRESULT result;
result = m_input->CreateDevice(GUID_SysMouse, &m_mouse, nullptr);
if (FAILED(result))
return false;
result = m_mouse->SetDataFormat(&c_dfDIMouse);
if (FAILED(result))
return false;
result = m_mouse->SetCooperativeLevel(m_hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(result))
return false;
result = m_mouse->Acquire();
if (FAILED(result))
return false;
return true;
}
bool InputClass::ReadMouse()
{
HRESULT result;
result = m_mouse->Poll();
if (FAILED(result))
return false;
result = m_mouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&m_mouseState);
if (FAILED(result))
{
if (DIERR_INPUTLOST == result || DIERR_NOTACQUIRED == result)
{
result = m_mouse->Acquire();
if (FAILED(result))
return false;
}
else
return false;
}
return true;
}
void InputClass::ProcessMouse()
{
m_mouseX += m_mouseState.lX;
m_mouseY += m_mouseState.lY;
}
void InputClass::GetJoystickPosition(int& joysticlX, int& joystickY)
{
joysticlX = m_joystickState.lX;
joystickY = m_joystickState.lY;
}
bool InputClass::InitializeJoystick()
{
m_input->EnumDevices(DI8DEVTYPE_JOYSTICK, (LPDIENUMDEVICESCALLBACKW)EnumJoysticks, this, DIEDFL_ATTACHEDONLY);
if (!m_joystick)
return false;
return true;
}
bool CALLBACK InputClass::EnumJoysticks(LPCDIDEVICEINSTANCE instance, LPVOID ptrParam)
{
InputClass* currentInput;
HRESULT result;
DIPROPRANGE axisRange;
DIPROPDWORD deadBand;
currentInput = (InputClass*)ptrParam;
result = currentInput->m_input->CreateDevice(instance->guidInstance, ¤tInput->m_joystick, nullptr);
if (FAILED(result))
return DIENUM_CONTINUE;
result = currentInput->m_joystick->SetDataFormat(&c_dfDIJoystick);
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
result = currentInput->m_joystick->SetCooperativeLevel(currentInput->m_hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
::ZeroMemory(&axisRange, sizeof(DIPROPRANGE));
axisRange.diph.dwSize = sizeof(DIPROPRANGE);
axisRange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
axisRange.diph.dwObj = DIJOFS_X;
axisRange.diph.dwHow = DIPH_BYOFFSET;
axisRange.lMin = -1024;
axisRange.lMax = 1024;
result = currentInput->m_joystick->SetProperty(DIPROP_RANGE, &axisRange.diph);
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
axisRange.diph.dwObj = DIJOFS_Y;
result = currentInput->m_joystick->SetProperty(DIPROP_RANGE, &axisRange.diph);
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
deadBand.diph.dwSize = sizeof(DIPROPDWORD);
deadBand.diph.dwHeaderSize = sizeof(DIPROPHEADER);
deadBand.diph.dwObj = DIJOFS_X;
deadBand.diph.dwHow = DIPH_BYOFFSET;
deadBand.dwData = 1500;
result = currentInput->m_joystick->SetProperty(DIPROP_DEADZONE, &deadBand.diph);
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
deadBand.diph.dwObj = DIJOFS_Y;
result = currentInput->m_joystick->SetProperty(DIPROP_DEADZONE, &deadBand.diph);
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
result = currentInput->m_joystick->Acquire();
if (FAILED(result))
{
currentInput->m_joystick->Release();
currentInput->m_joystick = nullptr;
return DIENUM_CONTINUE;
}
return DIENUM_STOP;
}
bool InputClass::ReadJoystick()
{
HRESULT result;
if (m_joystick != nullptr)
{
result = m_joystick->Poll();
if (FAILED(result))
return false;
result = m_joystick->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID)&m_joystickState);
if (FAILED(result))
{
if (DIERR_INPUTLOST == result || DIERR_NOTACQUIRED == result)
{
result = m_joystick->Acquire();
if (FAILED(result))
return false;
}
else
return false;
}
}
return true;
}
源码下载:下载地址