본문 바로가기
프로그래밍/공부

[Game] 각도와 방향

by Sik.K 2023. 1. 1.

게임에서 반사는 어떻게 구현할까?

 

반사는 정반사와 난반사가 있다.

 

정반사는 입사된 각의 완전 반대방향으로 반사가 되어 나가는 것이다.

 

이를 위해서 투영 벡터라는 것을 우선 알아둘 필요가 있다.

 

투영 벡터란, A 벡터와 B 벡터를 내적할 때, 그 결과값이 B 벡터 상에 나타나는데 이를 투영 벡터라고 한다.

 

사실 이 글을 작성하는 필자도 문과이고 많은 문과들이 벡터에 대한 개념을 잡기가 어려운 것을 알고 있다.

 

쉽게 생각하면 이와 같다.

 

반사를 할 때 정반사의 경우 반사각은 입사각에서 그대로 90도를 더하거나 뺀 값이 된다. 그 90도라는 것은 결국 가상의 벡터가 되어 반사각과 입사각 사이에서 중심이 된다.

 

이 90도를 가상의 벡터라고 가정하고 이 벡터와 입사각을 내적한 결과가 투영 벡터가 되고, 이 투영 벡터를 이용해서 입사 벡터의 완전한 반사 벡터를 구할 수 있다.

 

void Bullet::Reflection(ObLine axisX, ObLine axisY)
{
	Vector2 projectionX = Vector2(axisX.GetWorldPivot().x, missile.GetWorldPivot().y) - Vector2(axisX.GetWorldPivot());
	Vector2 projectionY = Vector2(missile.GetWorldPivot().x, axisY.GetWorldPivot().y) - Vector2(axisY.GetWorldPivot());
	Vector2 dir = lastPos - missile.GetWorldPivot();


	float seta = Utility::DirToRadian(dir) / ToRadian;
	
	Vector2 inner_product;
	Vector2 Reflection;

	if (isOutLineX())
	{
		// 투영 벡터
		inner_product = Vector2(dir.x * projectionX.x, dir.y * projectionX.y);	
		inner_product.Normalize();

		// 투영 벡터를 이용해서 반사벡터를 구하는 공식
		Reflection = dir + 2 * inner_product * (-dir * inner_product);
		missile.rotation = Utility::DirToRadian(Reflection);			
	}
	else if (isOutLineY())
	{
		inner_product = Vector2(dir.x * projectionY.x, dir.y * projectionY.y);
		inner_product.Normalize();
		Reflection = dir + 2 * inner_product * (-dir * inner_product);
		missile.rotation = Utility::DirToRadian(Reflection);
	}

	this->lastPos = missile.GetWorldPivot();
}

bool Bullet::isOutCAM()
{
	float x, y, lineX, lineY;
	x = missile.GetWorldPivot().x;
	y = missile.GetWorldPivot().y;
	lineX = CAM->position.x;
	lineY = CAM->position.y;

	if (x >= lineX + app.GetHalfWidth() ||
		x <= lineX - app.GetHalfWidth() ||
		y >= lineY + app.GetHalfHeight() ||
		y <= lineY - app.GetHalfHeight())
		return true;

	return false;
}

bool Bullet::isOutLineX()
{
	float x, lineX;
	x = missile.GetWorldPivot().x;
	lineX = CAM->position.x;

	if (x >= lineX + app.GetHalfWidth() || x <= lineX - app.GetHalfWidth())
		return true;
	else
		return false;
}

bool Bullet::isOutLineY()
{
	float y, lineY;
	y = missile.GetWorldPivot().y;
	lineY = CAM->position.y;

	if (y >= lineY + app.GetHalfHeight() || y <= lineY - app.GetHalfHeight())
		return true;
	else
		return false;
}

 

밖으로 나갔는지 확인하는 함수와 반사각을 구해 발사된 미사일을 반사시키는 함수이다.

 

 

 

'프로그래밍 > 공부' 카테고리의 다른 글

[DirectX] 셰이더(Shader)  (0) 2023.01.04
[DirectX] 렌더링 파이프라인 - (1)  (0) 2023.01.04
[Game] 객체의 회전 part.2  (0) 2022.12.22
[Game] 객체의 회전  (0) 2022.12.19
[Game] 변환행렬  (2) 2022.12.15

댓글