F.R.I.D.A.Y.

원의 충돌 판정 본문

DEV/C C++

원의 충돌 판정

F.R.I.D.A.Y. 2021. 5. 8. 01:10
반응형

게임이란 현대 기술의 정점을 모두 포함하고 있는 기술의 정수다

 

 문득 이런 구절이 떠오르는 포스트가 아닐까 생각합니다. 누가 말했는지는 몰라도 정말 한번에 와 닿는 말이 아닐 수 없습니다. RPG에서만 보더라도 다양한 물리 법칙이 적용된 엔진[# 유니티와 언리얼이 대표적이죠]이 사용되고, FPS 게임에서는 심지어 탄도학도 이용[# 단순히 배틀그라운드 탄도학만 검색해도 나오는 글이 수 십 개...]합니다.

 

 게임에서 중요한 것 중 하나가 막혀 있는 곳을 가지 못하는 것이라 생각합니다. 생각해보세요. 현실에서 물건을 짚으려 손을 뻗었는데 짚이기는 커녕 그 물건을 통과해버린다면. 아마도 기절하지 않을까요?

 

 그래서 게임에서는 물리 엔진을 사용합니다. 사실 게임에만 사용한다기보단, 여러 산업 전반에서 사용하고 있죠. 건축할 때 어떻게 지어야 하중을 견딜 수 있는지 무너지지는 않는지 시뮬레이션을 하고, 영화 인터스텔라에서도 물리엔진을 적용해 생생한 블랙홀 영상을 만들어냈죠.

 

 이번 포스트에서는 충돌 판정, 그 중에서도 원의 충돌 판정을 이야기 합니다.


원의 충돌 판정

 원의 방정식은 다음과 같습니다.

 이 때, 원은 네가지 경우를 볼 수 있습니다.

 만나지 않은 경우, 한 점만 만난경우[# 이경우, 접촉을 했는지 안했는지에 대한 관점은 사람마다 다를 수 있지만 여기서는 없는걸로 칩니다.], 일부 겹쳐 두 점으로 만난경우, 중심이 같은 경우로 볼 수 있겠네요. 비교 공식은 다음과 같습니다.

두 점의 간격 거리가 반지름의 합보다 작으면 되므로, 아래로 변형할 수 있습니다.

 

근호는 양측에 존재하니 삭제해도 무방하다

 

 두 점사이 거리가 반지름의 합보다 작으면 충돌이 일어난 것으로 판단할 수 있으므로 등호는 < 부등호로 변경해 사용합니다.

bool CollisionCircle(Circle r1, Circle r2){
	if(r1.x == r2.x && r1.y == r2.y) return true;
    
    float dist = pow(r1.x - r2.x, 2) + pow(r1.y - r2.y, 2);
    float r = pow(r1.radius + r2.radius, 2);
    
    if(dist < r) return true;
    return false;
}
더보기

# Circle 자료형

 Circle 자료형은 임의로 생성한 자료형입니다. 중심점의 좌표값과 원의 반지름을 의미하는 radius 멤버를 가지고 있습니다. x와 y값은 정수타입으로 기준을 정했으며, 만일 정수 타입이 아니라 실수형 타입을 사용한다면 위의 코드처럼 작성하면 안됩니다. 이에 대해 더 자세한 내용은 아래 포스트를 참고하세요.

 

부동소수점은 ==으로 비교하지 마세요

말 그대로 부동 소수점, C/C++에서는 float나 double로 불리는 자료형은 == 연산자로 비교해서는 안됩니다.  그 이유를 알아봅시다. 3.14 == 3.14는 거짓일 수 있습니다.  3.14를 비교하는 코드를 보겠습

pang2h.tistory.com

 첫 번째에서 중심점의 위치가 같은지를 판단하는 이유는 아래에서 반지름의 합과 두 점 사이간의 거리를 구하는 속도보다 훨씬 빠르기 때문입니다.

 

 이 코드에서 한 점에서 만난 경우[# 반지름의 합과 두 점 사이 거리가 같은 경우]는 충돌로 판단하지 않습니다. 만일 충돌로 표현하려 한다면 비교를 하는 if 구문에서 부등호를 <=로 수정해야합니다.

 

# index

728x90
반응형
Comments