1. 역삼각함수
(1) arccos(아크 코사인)
각도 θ 를 구하기 위해 y = cosθ의 함수를 이렇게 나타낼 수 있다.
θ = cos(y^(-1)) 또는 θ = arccos(y)
( θ 의 범위 : 0 < θ < π )
아크 코사인의 값은 -1 부터 1이다.
(2) arcsin(아크 사인)
( θ 의 범위 : -π / 2< θ < π / 2 )
아크 사인의 값은 -1 부터 1이다.
(3) arctan(아크 탄젠트)
( θ 의 범위 : -π / 2< θ < π / 2 )
아크 탄젠트의 값은 - ∞ 부터 ∞ (마이너스 무한대 부터 무한대)이다.
2. 벡스텝
뒤치기를 하면 추가적인 데미지를 주는 방식이다.
(1) 몬스터의 주시 방향 설정
Monster.h에서 수정한다.
private:
Vector _lookPos = {};
Vector _lookDir = {};
};
이어서 몬스터의 기본값을 세팅하기 위해 Monster.cpp에서 아래와 같이 수정한다.
void Monster::Init()
{
_stat.hp = 100;
_stat.maxHp = 100;
_stat.speed = 10;
_pos = Pos{ 400, 300 };
// 바라보고 있는 좌표
_lookPos = Pos{ 400, 70 };
_lookDir = _lookPos - _pos;
_lookDir.Normalize();
}
void Monster::Update()
{
}
void Monster::Render(HDC hdc)
{
Utils::DrawCircle(hdc, _pos, 100);
// 몬스터가 바라보는 앞 방향을 그린다
HPEN pen = ::CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HPEN oldpen = (HPEN)::SelectObject(hdc, pen);
{
Utils::DrawLine(hdc, _pos, _lookPos);
}
::SelectObject(hdc, oldpen);
::DeleteObject(pen);
GameScene.cpp에서 설정되어 있는 몬스터의 기본 좌표를 제거한다.
{
Monster* monster = GET_SINGLE(ObjectManager)->CreateObject<Monster>();
GET_SINGLE(ObjectManager)->Add(monster);
}
(2) 몬스터의 중심과 마우스 사이의 벡터를 만들기
다시 Monster.cpp로 돌아와 Render 함수를 수정한다.
// 몬스터와 마우스의 벡터를 단위벡터로 만들기
Vector mousePos = GET_SINGLE(InputManager)->GetMousePos();
Vector monsterToMouseDir = mousePos - _pos;
monsterToMouseDir.Normalize();
두 벡터는 모두 정규화되어 있기 때문에 내적 결과가 1 * 1 * cos θ가 된다.
Vector dir = _lookDir;
dir.Normalize();
float dot = monsterToMouseDir.Dot(dir);
// 라디안
float radian = ::acos(dot);
float angle = radian * 180 / 3.14f;
아크 코사인으로 구한 값은 라디안이기 때문에, 비례식을 사용하여 '도'로 만들어준다.
이어서 게임 화면에 출력하는 아래의 코드를 작성하면 몬스터의 주시 방향과 마우스 사이의 각을 측정할 수 있다.
{
wstring str = std::format(L"angle({0})", angle);
Utils::DrawTextW(hdc, { 20, 50 }, str);
}
그러나 주시 방향과 마우스의 각도가 180도를 넘어가면 다시 줄어드는 것을 볼 수 있다.
이것은 아크 코사인의 최대값이 π(180도)이기 때문이다.
(3) 추가 보정
몬스터가 주시하는 축을 기준으로 180도가 넘어가면 270도, 360도 까지 도달할 수 있도록 보정하는 코드이다.
외적(Cross Product)를 사용하여, 두 벡터의 각이 180도가 넘으면 음수가 되는 원리를 이용한다.
float cross = dir.Cross(monsterToMouseDir);
if (cross < 0)
angle = 360 - angle;
{
wstring str = std::format(L"angle({0})", angle);
Utils::DrawTextW(hdc, { 20, 50 }, str);
}
이제 몬스터의 주시 각도가 바뀌어도 정상적으로 angle이 출력되는 것을 알 수 있다.
따라서 특정 angle 사이에 공격이 적중했을때 추가 보상을 줄 수 있게 된다.
'Windows API & 게임 수학' 카테고리의 다른 글
1-9. 리소스를 관리하는 매니저 클래스(LineMesh, ResourceManager) (0) | 2023.11.01 |
---|---|
2-4. 벡터의 외적을 활용하기 - 범위, 쿨타임 표시 (0) | 2023.10.30 |
2-3. 벡터의 내적을 이용해 마우스를 따라다니는 몬스터 구현 (0) | 2023.10.30 |
2-2. 벡터를 이용한 기능 개선 - 유도탄 (0) | 2023.10.26 |
2-1. 삼각함수를 이용하여 여러 각도로 발사하기 (1) | 2023.10.26 |