λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

[winAPI 06] Key Manager

@GAMEMING2024. 6. 4. 13:37

 

 

- κΈ°μ‘΄ ν‚€ μž…λ ₯ λ°©μ‹μ˜ 문제

 

 μš°μ„  λ°œμƒν•  수 μžˆλŠ” 첫 번째 상황은 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);
}

 

 

 

728x90

'🧐 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
GAMEMING
@GAMEMING :: GAMEMING

< School > ν•œκ΅­κ³΅ν•™λŒ€ν•™κ΅ κ²Œμž„κ³΅ν•™κ³Ό λ²€μ²˜μ°½μ—… 뢀전곡 < Instagram > μž‘μ—… @game.plan.diary 본계 @mi.___.02

μ†Œν†΅ ν™˜μ˜ν•©λ‹ˆλ‹€ πŸ‘€

λͺ©μ°¨