[DirectX]Programming.Role.Playing.Games:03_Input

        本来按照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, &currentInput->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;
}

源码下载:下载地址

猜你喜欢

转载自blog.csdn.net/zp288105109a/article/details/81104727