1. 내적

(1) 기하학적 정의 (위키백과)

두 벡터의 크기를 곱하고 cosθ( θ는 두 벡터 사이의 각도 )를 곱한 값.

 

 

(2) 정사영(수직사영, 위키백과)

{"originWidth":293,"originHeight":237,"style":"alignCenter","width":200,"height":162,"caption":"b에 정사영된

한 벡터를 다른 벡터에 사영하는 것.

(벡터 위에 불을 켜서 그 그림자를 다른 벡터에 가져다대는 것이라고 비유할 수 있다)

여기에서 정사영된 벡터를 구하려면 해당 정사영 값에 단위벡터를 곱해주면 된다.

( c = |a|cos θ * ( b / |b| ) )

 

 

2. 마우스를 따라 움직이는 몬스터 구현

(1) 내적 구현 (Types.h)

	float Dot(Vector other)
	{
		return x * other.x + y * other.y;
	}

벡터를 좌표로 나타내었을 때 a(x1, y1), b(x2, y2) 의 두 벡터를 내적한 결과는

x1*x2 + y1*y2 이다.

 

(2) 사양 변경

GameScene.cpp에서 몬스터가 마우스에 따라 움직이도록 변경할 것이므로, 플레이어 생성코드를 지우고, 몬스터를 1마리, 400, 400에 스폰하도록 변경한다.

void GameScene::Init()
{
	// 몬스터 1마리 생성
	{
		//for (int32 i = 0; i < 5; i++)
		{
			Monster* monster = GET_SINGLE(ObjectManager)->CreateObject<Monster>();
			monster->SetPos(Pos{ 400, 400});
			GET_SINGLE(ObjectManager)->Add(monster);
		}
	}
}

Monster.h에 몬스터가 움직이는 시작과 끝 벡터를 지정한다.

private:
	Vector _start = { 300, 100 };
	Vector _end = { 600, 250 };
};

 

이어 Monster.cpp에서 몬스터가 움직이는 경로를 빨간색으로 그려보자.

void Monster::Render(HDC hdc)
{
	Utils::DrawCircle(hdc, _pos, 50);

	HPEN pen = ::CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
	HPEN oldpen = (HPEN)::SelectObject(hdc, pen);
	{
		Utils::DrawLine(hdc, _start, _end);
	}
	::SelectObject(hdc, oldpen);
	::DeleteObject(pen);

}

몬스터는 여기에서 그려진 빨간색 선을 따라 이동하게 될 것이다.

 

(3) 시작점에서 마우스까지의 벡터 구하기

(3-1) Types.h

헤더에 <windows.h>를 추가한다.

먼저 POINT 타입과 Vector 타입은 서로 호환이 되지 않기 때문에, 우리가 구현한 Vector 클래스의 생성자를 추가해준다.

struct Vector
{
	Vector() {}
	Vector(float x, float y) : x(x), y(y) { }
	Vector(POINT pt) : x((float)pt.x), y((float)pt.y) { }

 

(3-2) Monster.cpp

헤더에 "InputManager.h"를 추가한다.

void Monster::Update()
{
	Vector mousePos = GET_SINGLE(InputManager)->GetMousePos();
	// 이동 경로의 벡터 계산
	Vector v1 = _end - _start;

	// 마우스에서 시작점 까지의 벡터
	Vector v2 = mousePos - _start;
}

이제 v1 벡터에 정사영된 v2 벡터를 구할 것이다.

	v1.Normalize();
	float dot = v1.Dot(v2);
	Pos pos = _start + v1 * dot;

	_pos = pos;
}

v1를 단위벡터로 만들어주고 v2와 내적을 하면 v2의 정사영된 벡터 크기인 dot = |v2|cos θ를 구할 수 있다.

이제 시작 위치에 v1 단위 벡터와 정사영 벡터 크기를 곱한 값을 더해주면 된다.

만약 이 선을 벗어나지 못하게 하려면 아래와 같이 코드를 수정하면 된다.

	float maxLength = v1.Length();
	v1.Normalize();
	float dot = v1.Dot(v2);
	Pos pos = _start + v1 * dot;

	if (dot < 0 || dot > maxLength)
		return;

	_pos = pos;
}

마우스와 시작점 사이의 각이 직각을 넘어 둔각이 되거나, 선의 길이를 벗어나지 못하게 구현한 코드이다.