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 사이에 공격이 적중했을때 추가 보상을 줄 수 있게 된다.