League Of Legends - Link Select [winAPI 06] Key Manager
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค“ Study/winAPI

[winAPI 06] Key Manager

by GAMEMING 2024. 6. 4.
728x90

 

 

- ๊ธฐ์กด ํ‚ค ์ž…๋ ฅ ๋ฐฉ์‹์˜ ๋ฌธ์ œ

 

 ์šฐ์„  ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ƒํ™ฉ์€ A์™€ B ๋ฌผ์ฒด๊ฐ€ ์ด๋™ํ•˜๋Š” ๊ฒŒ์ž„์—์„œ ํ‚ค ๋งค๋‹ˆ์ €๊ฐ€ ์—†๋‹ค๋ฉด, ๊ฐ ๋ฌผ์ฒด๋Š” ์ž์‹ ์˜ ํ‚ค ์ž…๋ ฅ์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋  ๊ฒฝ์šฐ ํ‚ค๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ˆ˜ ๋ฐฑ ๋ฒˆ์˜ ์ƒํ™ฉ ์ค‘์— A ๋ฌผ์ฒด๋Š” ํ˜„์žฌ ํ”„๋ ˆ์ž„์—์„œ ์ด๋™์„ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ, B ๋ฌผ์ฒด๋Š” ๋‹ค์Œ ํ”„๋ ˆ์ž„์—์„œ ์ด๋™์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ์œ ์ €์˜ ์ž…์žฅ์—์„œ A ๋ฌผ์ฒด๋Š” ๋จผ์ € ์ด๋™ํ•˜๊ณ , B ๋ฌผ์ฒด๋Š” ์•ฝ๊ฐ„์˜ ์ง€์—ฐ ํ›„์— ์ด๋™ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ๋œ๋‹ค. 

 

 ๋‘ ๋ฒˆ์งธ ์ƒํ™ฉ์€ ์šฐ๋ฆฌ๊ฐ€ ์ ํ”„ ๊ฒŒ์ž„์„ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ์งง๊ฒŒ ์ ํ”„ํ•  ๋•Œ์™€ ๊ธธ๊ฒŒ ์ ํ”„๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ๋‚ ๋ผ๊ฐ€๋Š” ํญ๊ณผ ๊ฑฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฅด๊ฒŒ ์„ค๊ณ„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด, ์ด๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•  ๊ฒƒ์ธ๊ฐ€?

 

 ํ˜„์žฌ ์šฐ๋ฆฌ๊ฐ€ ์ž‘์—…ํ•˜๋Š” ๊ตฌ์กฐ๋Š” ๋งค ์ˆœ๊ฐ„์ˆœ๊ฐ„ UPDATE ํ•จ์ˆ˜๋ฅผ ํ™•์ธํ•˜๊ณ , ๋ชจ๋“  ์—…๋ฐ์ดํŠธ๊ฐ€ ๋๋‚˜๋ฉด ์ด ๋ณ€๊ฒฝ์ ์„ ๋ฐ˜์˜ํ•˜์—ฌ ๊ทธ๋ฆฌ๊ณ  ์žˆ๋‹ค. ์ด ๊ณผ์ •์ด 1ํ”„๋ ˆ์ž„์˜ ๊ณผ์ •์ด๊ณ  ์ด ํ•œ ํ”„๋ ˆ์ž„์— ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ DT๋ผ๊ณ  ํ•จ. ex) 900ํ”„๋ ˆ์ž„์ด๋ผ ํ•˜๋ฉด 1์ดˆ์— 900๋ฒˆ ์ž‘์—…ํ•จ

 ์šฐ๋ฆฌ๋Š” ํ•œ ํ”„๋ ˆ์ž„ ์‹œ๊ฐ„(DT)์ด ์ง€๋‚œ ํ›„์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ณผ ์ˆ˜ ์žˆ๊ธฐ์—, ๊ทธ ๋ฌผ์ฒด๊ฐ€ ๋”ฐ๋กœ๋”ฐ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์—†์Œ. A์˜ ๋ฌผ์ฒด๊ฐ€ ๋จผ์ € ์ด๋™ํ•˜๊ณ  ๊ทธ ํ›„ B๊ฐ€ ์ด๋™ํ–ˆ๋”๋ผ๋„, ํ•œ DT์•ˆ์—์„œ ์ผ์–ด๋‚ฌ์œผ๋ฉด ์ด๋Š” ์œ ์ €๊ฐ€ ๋ดค์„ ๋•Œ ๊ฑ ๋™์‹œ์— ์›€์ง์ด๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฆ„ ์—†์Œ. ํ•œ ํ”„๋ ˆ์ž„์—์„œ ์ ์šฉ๋œ ํ‚ค๋Š” ๋ฌด์กฐ๊ฑด ๊ฐ™์€ ์ด๋ฒคํŠธ๋กœ ์ฒ˜๋ฆฌ๋˜์–ด์•ผ ํ•œ๋‹ค.

 

 

- Key Manager๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

 

 1) ํ”„๋ ˆ์ž„ ๋™๊ธฐํ™” : ๋™์ผ ํ”„๋ ˆ์ž„์—์„œ ์ผ์–ด๋‚œ ์ผ์€ ๊ฐ™์€ ํ‚ค์— ๋Œ€ํ•ด ๋™์ผํ•œ ์ด๋ฒคํŠธ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•จ.

 2) ํ‚ค ์ž…๋ ฅ์„ ์—ฌ๋Ÿฌ ์ด๋ฒคํŠธ๋กœ ๋‚˜๋ˆ  ์ฒ˜๋ฆฌ : TAP, HOLD, AWAY, NONE

 

// KeyManager.h

enum class KEY_STATE {
	NONE,	
	TAP,	
	HOLD,	
	AWAY,
};

enum class KEY {
	LEFT,
	RIGHT,
	UP,
	DOWN,
	Q, 
	W, 
	E,
	R,
	T, 
	Y,
	U,
	I, 
	O, 
	P,
	A,
	S,
	D, 
	F,
	G, 
	Z, 
	X, 
	C,
	V,
	B,
	ALT,
	CTRL,
	LSHIFT,
	SPACE,
	ENTER,
	ESC,

	LAST,
};

struct keyInfo {
	KEY_STATE	state;
	bool		prev;
};

class KeyManager
{
	SINGLE(KeyManager);
private:
	vector<keyInfo>	vecKey;

public:
	void init();
	void update();

public:
	KEY_STATE GetKeyState(KEY key) { return vecKey[(int)key].state; }
};

 

 

 1) ํ‚ค ์ž…๋ ฅ ์ด๋ฒคํŠธ ์ •์˜ โ†’ enum class KEY_STATE

  ํ‚ค ์ด๋ฒคํŠธ๋ฅผ ์ •์˜ํ•œ๋‹ค.

  NONE - ์ด์ „ ํ”„๋ ˆ์ž„์—๋„ ๋ˆŒ๋ฆฌ์ง€ ์•Š๊ณ , ํ˜„์žฌ ํ”„๋ ˆ์ž„์—์„œ๋„ ๋ˆŒ๋ฆฌ์ง€ ์•Š์Œ.

  TAP - ์ด์ „ ํ”„๋ ˆ์ž„์—๋Š” ๋ˆŒ๋ฆฌ์ง€ ์•Š๊ณ , ํ˜„์žฌ ํ”„๋ ˆ์ž„์— ๋ง‰ ๋ˆŒ๋ฆผ.

  HOLD - ์ด์ „ ํ”„๋ ˆ์ž„์—๋„ ๋ˆŒ๋ ธ๊ณ , ํ˜„์žฌ ํ”„๋ ˆ์ž„์—๋„ ๋ˆŒ๋ฆผ.

  AWAY -  ์ด์ „ ํ”„๋ ˆ์ž„์—” ๋ˆŒ๋ ธ๋Š”๋ฐ, ํ˜„์žฌ ํ”„๋ ˆ์ž„์—์„œ๋Š” ๋ˆŒ๋ฆฌ์ง€ ์•Š์Œ. (๋ง‰ ๋—Œ)

 

 2) ์ง€์›ํ•  ํ‚ค ์ •์˜ โ†’ enum class KEY

 ์ด ํ”„๋กœ๊ทธ๋žจ ๋‚ด์—์„œ ์–ด๋–ค ํ‚ค๋ฅผ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ์ง€ ์ •์˜ํ•˜์ž.

 

 3) ํ‚ค ์ •๋ณด ๊ตฌ์กฐ์ฒด โ†’ struct keyInfo

  ํ‚ค ์ƒํƒœ๊ฐ’(state)๊ณผ ์ด์ „ ํ”„๋ ˆ์ž„์—์„œ ํ‚ค๊ฐ€ ๋ˆŒ๋ ธ๋Š” ์ง€(prev)์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค.

 

  4) KeyManager Class

  vector<keyInfo> vecKey โ†’ ํ‚ค ์ƒํƒœ ์ •๋ณด๋Š” ๋ฒกํ„ฐ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. 

  KEY_STATE GetKeyState(KEY key) โ†’ ํŠน์ • ํ‚ค์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜

 

// KeyManager.cpp

#include "pch.h"
#include "KeyManager.h"

#include "Core.h"

int arrVK[(int)KEY::LAST] =
{
	VK_LEFT,	// LEFT,
	VK_RIGHT,	// RIGHT,
	VK_UP,		// UP,
	VK_DOWN,	// DOWN,
	'Q',
	'W',
	'E',
	'R',
	'T',
	'Y',
	'U',
	'I',
	'O',
	'P',
	'A',
	'S',
	'D',
	'F',
	'G',
	'Z',
	'X',
	'C',
	'V',
	'B',
	VK_MENU,	// ALT,
	VK_CONTROL,	// CTRL,
	VK_LSHIFT,	// LSHIFT,
	VK_SPACE,	// SPACE,
	VK_RETURN,	// ENTER,
	VK_ESCAPE,	// ESC,

	// LAST, 
};

KeyManager::KeyManager()
{

}

KeyManager::~KeyManager()
{

}

void KeyManager::init()
{
	for (int i = 0; i < (int)KEY::LAST; ++i) {
		vecKey.emplace_back(keyInfo{ KEY_STATE::NONE, false });
	}
	// std::cout << "vecKey size after init: " << vecKey.size() << std::endl;
}

void KeyManager::update()
{
	// HWND mainWnd = Core::Instance()->getMainHandle();
	HWND hWnd = GetFocus();

	// ์œˆ๋„์šฐ ํฌ์ปค์‹ฑ ์ค‘์ผ ๋•Œ
	if (nullptr != hWnd) {
		// ๋ชจ๋“  ํ‚ค์— ๋Œ€ํ•ด์„œ
		for (int i = 0; i < (int)KEY::LAST; ++i) {
			if (GetAsyncKeyState(arrVK[i]) & 0x8000) {	// ํ‚ค๊ฐ€ ๋ˆŒ๋ ค์žˆ๋‹ค
				if (vecKey[i].prev) {	// ์ด์ „์—๋„ ๋ˆŒ๋ ค์žˆ์—ˆ๋‹ค.
					vecKey[i].state = KEY_STATE::HOLD;
				}
				else {
					vecKey[i].state = KEY_STATE::TAP;
				}
				vecKey[i].prev = true;
			}
			else {	// ํ‚ค๊ฐ€ ์•ˆ๋ˆŒ๋ ค์žˆ๋‹ค.
				if (vecKey[i].prev) {	// ์ด์ „์—๋„ ๋ˆŒ๋ ค์žˆ์—ˆ๋‹ค.
					vecKey[i].state = KEY_STATE::AWAY;
				}
				else {
					vecKey[i].state = KEY_STATE::NONE;
				}
				vecKey[i].prev = false;
			}
		}
	}
	else {	// ํฌ์ปค์‹ฑ ์•„๋‹ ๋•Œ
		for (int i = 0; i < (int)KEY::LAST; ++i) {
			vecKey[i].prev = false;
			if (KEY_STATE::TAP == vecKey[i].state || KEY_STATE::HOLD == vecKey[i].state)
				vecKey[i].state = KEY_STATE::AWAY;
			else if (KEY_STATE::AWAY == vecKey[i].state)
				vecKey[i].state = KEY_STATE::NONE;
		}
	}
}

 

 

 ๋‚ด๊ฐ€ ๋งŒ๋“  ํ‚ค์™€ ์‹ค์ œ ๊ฐ€์ƒํ‚ค๋ฅผ ์กฐํ•ฉํ•ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค โ†’ arrVK()

 ์‹ค์ œ ์œˆ๋„์šฐ ๋‚ด์˜ ๊ฐ€์ƒํ‚ค์™€ ์•„์Šคํ‚ค์ฝ”๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ž‘์„ฑํ•˜๋„๋ก ํ•œ๋‹ค.

 

 ํ‚ค ๋งค๋‹ˆ์ €์˜ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜์—์„œ๋Š” ๊ฐ ํ‚ค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ NONE, false๋กœ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ํ‚ค ์ •๋ณด ๋ฒกํ„ฐ์— ์‚ฝ์ž…ํ•œ๋‹ค.

 

 ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜์—์„œ๋Š” ์œˆ๋„์šฐ ํฌ์ปค์‹ฑ์„ ์•Œ์•„๋‚ด์•ผ ํ•˜๋Š”๋ฐ '์œˆ๋„์šฐ ํฌ์ปค์‹ฑ'์ด๋ž€ ํ˜„์žฌ ์œ ์ €๊ฐ€ ์œˆ๋„์šฐ ์ฐฝ์„ ํฌ์ปค์‹ฑ ์ค‘์ธ๊ฐ€? ์— ํ•ด๋‹นํ•˜๋Š” ๋‚ด์šฉ์ด๋‹ค. ๋งŒ์•ฝ ์œˆ๋„์šฐ ์ฐฝ์ด ๋‚ด๋ ค๊ฐ”์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›๋Š” ์ƒํƒœ๋ผ๋ฉด ๊ฒŒ์ž„ ๋‚ด์—์„œ ์ด์ƒํ•˜๊ฒŒ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.

 ํ˜„์žฌ ๋ฉ”์ธ ์ฐฝ์œผ๋กœ๋งŒ ํฌ์ปค์‹ฑํ•˜๋ ค๋ฉด ์ฃผ์„์œผ๋กœ ์ฒ˜๋ฆฌ๋œ HWND mainWnd = Core::Instance()->getMainHandle(); ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋‚˜ ํ˜„์žฌ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” ๋งŒ๋“ค์–ด์ง„ ๋ชจ๋“  ์ฐฝ์— ๋Œ€ํ•ด์„œ ์ž…๋ ฅ์„ ๋ฐ›๊ธฐ ์œ„ํ•จ์œผ๋กœ hWnd๊ฐ€ null์ด ์•„๋‹ ๋•Œ๋งŒ ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›๋„๋ก ํ•œ๋‹ค.

 

์œˆ๋„์šฐ ํฌ์ปค์‹ฑ ์ค‘์ผ ๋•Œ ๋ชจ๋“  ํ‚ค์— ๋Œ€ํ•ด์„œ ํ˜„์žฌ ๋ˆŒ๋ ธ๋Š”์ง€์™€ ์•ˆ๋ˆŒ๋ ธ๋Š”์ง€, ์ด์ „์— ๋ˆŒ๋ ธ๋Š”์ง€์™€ ์•ˆ๋ˆŒ๋ ธ๋Š”์ง€๋ฅผ ์ฒดํฌํ•ด ๊ฐ ์ƒํƒœ ์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•œ๋‹ค.

 

ํ‚ค ๋งค๋‹ˆ์ €๋ฅผ Core.cpp์— ์ ์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

// Core.cpp
#include "KeyManager.h"	// ์ถ”๊ฐ€

int Core::Init(HWND _handle, POINT _ptResolution)
{

	// ...
	TimeManager::Instance()->Init();
	KeyManager::Instance()->init();	// ์ถ”๊ฐ€
    
    // ...
}

void Core::Progress()
{
	// Manager update
	TimeManager::Instance()->update();
	KeyManager::Instance()->update();	// ์ถ”๊ฐ€

	Update();

	Render();
}


void Core::Update()
{
	Vec2 vPos = obj.getPos();

	// ์ˆ˜์ •
	if (KeyManager::Instance()->GetKeyState(KEY::LEFT)==KEY_STATE::AWAY) {
		vPos.x -= 200.f * TimeManager::Instance()->getfDT();
	}
	if (KeyManager::Instance()->GetKeyState(KEY::RIGHT) == KEY_STATE::AWAY) {
		vPos.x += 200.f * TimeManager::Instance()->getfDT();
	}

	obj.setPos(vPos);
}

 

 

 

'๐Ÿค“ Study > winAPI' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[winAPI 08] Object  (0) 2024.06.05
[winAPI 07] Scene & Scene Manager  (1) 2024.06.04
[winAPI 05] Double Buffering  (0) 2024.06.04
[winAPI 04] Timer  (0) 2024.04.09
[winAPI 03] Core class & Singleton  (0) 2024.04.08