24/03/19
13화. Win32API Key Manager (1)
문제점 :
1. 키 입력 동기화
Core::Update() 에서 키 입력을 받아주고 있다.
이 때문에 타이밍 차이로 한 프레임에서 동일한 키 입력에 대해서 다른 결과 값이 발생할 수 있다.
작업 처리를 할 때 키 입력을 할 때, 1번에 대한 작업을 처리 할 땐 key 입력이 있었는데 3번 작업을 하기 전에 키 입력이 종료되면 한 프레임에 안에서 동일 키 입렵에 대해 어떤 작업은 키 입력이 있던걸로 처리되고 또 다른 곳에선 키 입력이 없었던걸로 되는 문제가 발생한다.
DeltaTime이 흐를 때 한 프레임 안에서 입력된 변화는 순차적으로 작업을 할 뿐, 동시처리를 해줘야한다.
2. 키 입력에 대한 구체적인 정의
키 입력에 대해 구체적인 정의가 안되어 있다.
키의 상태로는 아래와 같이 총 4가지의 상태가 존재할 수 있는데 현재 그런 정의가 없다.
- TAP : 현재 시점에 키 입력 발생
- HOLD : 이전 시점에도 키 입력이 있었고, 현재 시점에도 키 입력이 유지되는 중
- AWAY : 이전 시점에는 키 입력이 있었지만, 현재 시점에는 키 입력이 없음
- NONE : 이전 시점에도 키 입력이 없었고, 현재 시점에도 키 입력이 없음
KeyMgr 클래스의 정의 이유 :
1. 동일 프레임 내에서 같은 키 입력에 대해서 동일한 이벤트가 발생됨을 보장해준다.
2. 키 입력에 대한 세분화 (TAP, HOLD, AWAY, NONE)
KeyMgr 클래스 설계 :
1. 입력을 받아줄 키 종류 정의
enum class KEY
{
LEFT, RIGHT, UP, DOWN,
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,
ALT, CTRL, LSHIFT, SPACE, ENTER, ESC,
LAST,
};
2. 키 상태 정의
enum class KEY_STATE
{
NONE,
TAP,
HOLD,
AWAY,
// AWAY, NONE 둘 다 안눌린 시점이다.
};
3. 키에 대한 정보를 저장할 구조체
struct tKeyInfo
{
KEY_STATE eState; // 키의 상태값(none, tap, hold, away)
bool bPrevPush; // 이전 프레임 눌림여부
};
4. 입력을 받아줄 키와 Window 가상 키 코드 매칭
int g_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', 'H', 'J', 'K', 'L',
'Z', 'X', 'C', 'V', 'B', 'N', 'M',
VK_MENU, // ALT
VK_CONTROL, // CTRL
VK_SHIFT, // LSHIFT
VK_SPACE, // SPACE
VK_RETURN, // ENTER,
VK_ESCAPE, // ESC
//LAST,
};
5. 키 이벤트 동기화 처리
키 입력에 대한 이벤트 처리가 발생하는 update() 함수 전에 CKeyMgr::update()에서 키 입력과 관련되 처리를 다 해주기에 이벤트 처리시 동일 프레임에선 동일한 키 입력 이벤트가 발생한다.
6. 키 입력상태 세분화
void CKeyMgr::update()
{
for (size_t i = 0; i < (size_t)KEY::LAST; ++i)
{
// 키가 눌려있다.
if (GetAsyncKeyState(g_arrVK[i]) & 0x8000)
{
if (m_vecKey[i].bPrevPush)
{
// 이전에도 눌려있었다.
m_vecKey[i].eState = KEY_STATE::HOLD;
}
else
{
// 이전에 눌려있지 않았다.
m_vecKey[i].eState = KEY_STATE::TAP;
}
m_vecKey[i].bPrevPush = true;
}
// 키카 안눌려있다.
else
{
if (m_vecKey[i].bPrevPush)
{
// 이전에는 눌려있었다.
m_vecKey[i].eState = KEY_STATE::AWAY;
}
else
{
// 이전에도 눌려있지 않았다.
m_vecKey[i].eState = KEY_STATE::NONE;
}
m_vecKey[i].bPrevPush = false;
}
}
}
14화. Win32API Key Manager (2)
문제점 :
키 입력을 하던 도중 화면이 내려가게 되면 키 입력 처리가 어떻게 되는가?
현재는 GetAsyncKeyState() 함수에 의해 메인 윈도우가 포커싱된 상태가 아니더라도 키 입력을 받을것이다.
하지만, 화면에 내려간다면 키 입력이 정상적으로 종료되도록 해줘야한다.
필요한 작업 :
1. 메인 윈도우가 포커싱 되어있지 않다면 키 입력을 받으면 안된다.
2. 키 입력을 받던 중 윈도우의 포커싱이 풀리면 키 입력이 정상적으로 종료되어야한다.
키 입력의 정상적인 종료란? :
아래의 순서대로 상태가 변하는 걸 의미한다.
TAP / HOLD -> AWAY -> NONE
GetFocus() :
GetFocus() 함수는 현재 포커싱된 윈도우의 핸들을 반환한다.
해당 함수를 사용하여 메인 윈도우의 핸들과 현재 포커싱중인 윈도우의 핸들을 비교한다.
비교 결과 메인 윈도우의 핸들값과 현재 포커싱중인 윈도우의 핸들값이 다르다면 키 입력을 받지 않도록 해준다.
또한 키 입력을 받는 중이었던 키들의 상태도 정상적으로 종료되도록 해준다.
메인 윈도우의 포커싱이 풀린 경우 :
TAP 또는 HOLD 상태에 있던 키 들은 AWAY 상태로
AWAY 상태에 있던 키들은 NONE 상태로 상태값이 순차적으로 바뀌도록 해준다.
for (size_t i = 0; i < (size_t)KEY::LAST; ++i)
{
m_vecKey[i].bPrevPush = false;
// TAP or HOLD => AWAY
if (KEY_STATE::TAP == m_vecKey[i].eState
|| KEY_STATE::HOLD == m_vecKey[i].eState)
{
m_vecKey[i].eState = KEY_STATE::AWAY;
}
// AWAY => NONE
else if (KEY_STATE::AWAY == m_vecKey[i].eState)
{
m_vecKey[i].eState = KEY_STATE::NONE;
}
}
15화. Win32API Scene Manager (1)
Object 객체 관리 :
Object 객체를 관리할 Scene 클래스 추가
Object 객체는 여러개의 그룹으로 나뉜다. ( std::vector<CObject*> vecGroup )
Object들을 그룹별로 분류해서 가지고 있는 컨테이너를 Scene 클래스에서 관리한다.
CObject 클래스의 그룹 개수는 최대 32개로 지정해줌 (임시)
Scene 클래스 :
CScene 클래스 역시 CObject 클래스와 마찬가지로 여러 종류의 Scene으로 나뉠것이기에 상속구조를 고려해줘야한다.
때문에 소멸자에 virtual 키워드를 붙여주고 Scene 클래스를 관리해주는 Manager 클래스를 만들어줘야한다.
상속 구조에 있을 때 생성자와 소멸자의 호출 순서는...
생성 : 부모 객체부터 / 소멸 : 자식 객체부터
#include <iostream>
class A
{
public:
A() { std::cout << "A 생성자" << std::endl; }
virtual ~A() { std::cout << "A 소멸자" << std::endl; }
};
class B : public A
{
public:
B() { std::cout << "B 생성자" << std::endl; }
virtual ~B() { std::cout << "B 소멸자" << std::endl; }
};
class C : public B
{
public:
C()
{
std::cout << "C 생성자" << std::endl;
}
virtual ~C() { std::cout << "C 소멸자" << std::endl; }
};
int main()
{
C* c = new C;
delete c;
return 0;
}

SceneMgr 클래스 :
Scene 의 종류는 얼마나 될지 가늠할 수 없길에 Object 객체의 그룹개수와 달리 별다른 값 지정을 해주지 않았다.
SceneMgr 클래스에서 Scene 클래스를 관리하기에 Init() 함수에서 Scene 객체를 생성해주고 SceneMgr 클래스의 소멸자에서 Scene 객체를 모두 메모리 해제해준다.
16화. Win32API Scene Manager (2)
프레임 워크 :
프레임 워크란 구조를 의미한다.
즉, 게임 프레임워크란 게임 엔진의 구조를 의미한다.
엔진 구조 설계 :
Core::progress() 에서 Scene 클래스를 관리하는 SceneMgr 의 update(), render() 함수를 호출한다.
SceneMgr 의 update(), render() 함수는 각각 자신이 관리하는 Scene 클래스들의 update(), render() 함수를 호출하고
Scene 클래스는 자신이 관리하는 Object 클래스의 update(), render() 클래스를 호출한다.
17화. Win32API Object (1)
실습 :
Player , Monster 클래스 추가
18화. Win32API Object (2)
실습 :
Missile 클래스 추가, Player 객체 Missile 발사 기능 추가
19화. Win32API 기초 수학 (1)
라디안(rad) :
호의 반지름과 호 둘레의 비율
1 rad= 원의 둘레 / 원의 지름(d) = 원 둘레의 절반 / 원의 반지름(r)
원주율(π) :
3.141592...
지름(d) * 원주율(π) = 원(호)의 둘레
라이안과 원주율의 관계 :
π / 3.141592... = 1 rad
π = 180˚ → 180˚ / 3.141592 ≒ 57.2˚
삼각함수 :
refer : https://blog.naver.com/lim4447/221587511188
refer : https://www.minzkn.com/moniwiki/wiki.php/TrigonometricalFunction
호의 둘레상에서 90를 넘어가면 x의 좌표값은 음수값을 가지고, 270도를 넘기면 x의 좌표값은 양수를 가진다.
y의 좌표값은 180도를 넘기면 음수값을 가지고, 360(=0)도를 넘기면 다시 양수값을 가진다.
때문에 호의 둘레상에서 x의 좌표는 cos그래프, y의 좌표는 sin그래프의 모습을 보인다.
코드 수정 :
삼각함수를 활용하여 미사일의 이동 방향을 구하는 공식을 수정
20화. Win32API 기초 수학 (2)
문제점 :
대각선 이동할때와 x,y축으로 평행하게 이동할 때의 속도가 다르다.
즉, 이동 방향에 따라 같은 시간동안 이동하는 거리가 달라진다.
피타고라스의 정리를 활용해서 삼각형의 빗변을 구해보면 결과는 아래와 같다.
반지름이 1인 원이 있다고 가정할 때 x축, y축 으로 이동할 때는 한번에 1을 이동하지만, 45˚ 방향으로 이동할땐 1.4만큼 이동한다. 때문에 각도에 상관없이 항상 일정한 길이만큼 이동하도록 보정을 해줘야한다.
정규화 Normalize :
벡터 (1,1) 의 길이가 1을 가지도록 만들어주는 과정을 "정규화 (Normalize)" 라고 한다.
정규화된 벡터를 "단위벡터" 라고 부르며 벡터는 크기와 방향을 나타내지만 단위벡터는 방향만 나타낸다.
정규화 공식 :
벡터의 크기(|v|)는 피타고라스의 정의로 구할 수 있다.
이때, 구해준 벡터의 크기로 각 좌표의 값을 나눠주면 단위벡터가 된다.
코드 수정 :
Vec2 구조체에 Length(), Normalize() 기능 추가
Normalize() 가 들어갔기에 "Vec2 m_vDir" 멤버를 추가하여 m_vDir.x / m_vDir.y 의 값을 이동값에 사용해줘도 된다.
// case1
{
vPos.x += m_fSpeed * fDT * cosf(m_fTheta);
vPos.y -= m_fSpeed * fDT * sinf(m_fTheta); // 윈도우 좌표에서 y의 값은 내려갈수록 값이 커진다.
}
// case2
{
vPos.x += m_fSpeed * fDT * m_vDir.x;
vPos.y -= m_fSpeed * fDT * m_vDir.y;
}
Next Note
Win32API 강의_4
24/03/20
coder-qussong.tistory.com
'Win32API' 카테고리의 다른 글
Win32API_StudyNote_6 (0) | 2024.03.24 |
---|---|
Win32API_StudyNote_5 (0) | 2024.03.22 |
Win32API_StudyNote_4 (0) | 2024.03.21 |
Win32API_StudyNote_2 (0) | 2024.03.17 |
Win32API_StudyNote_1 (0) | 2024.03.13 |