728x90
메세징시스템을 이용한다면 GetAsyncKeyState 함수를 사용해 키를 누르고 있는지 떼고있는지 홀드중인지의 확인이 가능하다 하지만 현재 진행중인 PeekMessage구조에서는 이 함수만으로의 정밀한 판단이 불가능하기 때문에 이 함수를 이용하며 새로운 키 매니저에 바인딩 시켜주고 상태를 따로 관리해야 한다
1. key binding
전역변수를 사용하여 WP(앞으로 축약하겠다)의 키들을 현재 내가 만든 키에 바인딩해준다
이렇게 하면 좋은점은 추후 앞으로 이동을 w가 아닌 s로 바꾼다면 전역변수의 w바인딩을 s로 바꿔주면 되기 때문에 동적으로 키입력을 바꾸는 것도 용이하다
int g_arrVK[(int)KEY::LAST] = {
VK_UP,
VK_DOWN,
VK_LEFT,
VK_RIGHT,
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P',
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L',
'Z', 'X', 'C', 'V', 'B', 'N', 'M',
VK_SPACE,
VK_ESCAPE,
VK_RETURN,
VK_MENU,
VK_CONTROL,
VK_SHIFT,
VK_TAB,
};
enum class KEY
{
UPARROW,
DOWNARROW,
LEFTARROW,
RIGHTARROW,
Q, W, E, R, T, Y, U, I, O, P,
A, S, D, F, G, H, J, K, L,
Z, X, C, V, B, N, M,
SPACE,
ESC,
ENTER,
ALT,
CTRL,
SHIFT,
TAB,
LAST,
};
2. Key 상태 관리
Key는 눌렀을경우 누르고있는중 떼었을경우 3가지가 주로 사용된다
이 3가지의 경우는 전 상태에 따라 변화되는데
DOWN -> HOLD -> UP 순으로 변화하는 것은 당연하고 때에 따라서는 HOLD는 생각될 수 도 있다.
enum class KEY_STATE
{
NONE, // 눌러진 적이 없는 상태
DOWN, // 키가 눌렸을 때
HOLD, // 키가 눌린 상태
UP, // 키가 떼졌을 때
};
struct tKeyInfo {
KEY_STATE eKeyState; // 현재 키의 상태
bool bPrevState; // 이전 프레임의 키 상태
};
class CKeyManager
{
SINGLETON(CKeyManager);
private:
vector<tKeyInfo> m_vecKey;
public:
KEY_STATE GetKeyState(KEY _eKey) { return m_vecKey[(int)_eKey].eKeyState; }
public:
void init(); // 키를 바인딩해 놓는다.
void update();
};
void CKeyManager::init()
{
for (int i = 0; i < (int)KEY::LAST; ++i) {
m_vecKey.push_back({ KEY_STATE::NONE, false });
}
}
3. 키 업데이트
이제 키 입력에따라 키의 상태를 변화시켜주면 된다
주의점 : 다른 프로그램을 작업하고 있는 중이면 현재 상황에 따라 현재 키 입력을 중지 시키고자 할 경우 GetFocus를 이용하여 확인하면 된다
void CKeyManager::update() {
// 윈도우 포커싱 알아내기
HWND hMainWnd = CCore::GetInstance()->GetMainHwnd();
HWND hWnd = GetFocus();
if (hWnd != nullptr) {
for (int i = 0; i < (int)KEY::LAST; ++i) {
if (GetAsyncKeyState(g_arrVK[i]) & 0x8000) {
if (m_vecKey[i].bPrevState) {
// 이전에 눌려있었다면
m_vecKey[i].eKeyState = KEY_STATE::HOLD;
}
else {
// 이전에 눌려있지 않았다면
m_vecKey[i].eKeyState = KEY_STATE::DOWN;
m_vecKey[i].bPrevState = true;
}
}
else {
if (m_vecKey[i].bPrevState) {
// 이전에 눌려있었다면
m_vecKey[i].eKeyState = KEY_STATE::UP;
m_vecKey[i].bPrevState = false;
}
else {
// 이전에 눌려있지 않았다면
m_vecKey[i].eKeyState = KEY_STATE::NONE;
}
}
}
}
// 포커싱이 아닌경우
else {
for (int i = 0; i < (int)KEY::LAST; ++i) {
m_vecKey[i].bPrevState = false;
if (m_vecKey[i].eKeyState == KEY_STATE::DOWN
|| m_vecKey[i].eKeyState == KEY_STATE::HOLD)
{
m_vecKey[i].eKeyState = KEY_STATE::UP;
}
else {
m_vecKey[i].eKeyState = KEY_STATE::NONE;
}
}
}
}
유니티의 InputSystem도 이처럼 구성되어 있지 않을까 생각해 본다
728x90
'windowAPI' 카테고리의 다른 글
WindowApi 6강 - range기반 for문의 주의점 (0) | 2024.11.23 |
---|---|
WindowAPi 5강 - SceneManager (0) | 2024.11.19 |
windowAPI - 3일차 double buffering (0) | 2024.11.18 |
WindowAPI 2일차 - 비동기 입력 및 싱글톤 (0) | 2024.11.18 |
WindowAPI 1일차 - 사각형 그리기 (0) | 2024.11.17 |