51. 원형 충돌
*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
[ 사전 지식 ]
HBRUSH PrevBrush = (HBRUSH)SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
//... 그림 그리기 ...
SelectObject(hDC, PrevBrush)
< GetStockObject() >
- 윈도우 API에서 기본으로 제공하는 HBRUSH 또는 HPEN을 사용한다.
- 우리가 사용할 기본 브러시는 HOLLOW_BRUSH이다. -> 사용 테두리만 있는 투명한 도형을 그려낼 수 있다.
- 윈도우 운영체제에서 기본으로 들고있는 오브젝트들 이므로, 손수 삭제할 필요가 없다.
HOLLOW_BRUSH를 사용할 경우 속을 투명하게 만들 수 있다...
하지만 총알같은 경우는 잘 안보이니까 투명하게 그릴 오브젝트들을 투명하게 그려 주고 다시 원래의 그리기 도구로 변경해 주자.
HPEN m_Pen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
- HPEN을 통해 우리가 그릴 도형의 색상을 설정할 수 있다.
--1번 인자: 실선/점선 등 선의 형태
--2번 인자: 선의 굵기
--3번 인자: RGB 색상
--- 자세한 내용은 MSDN을 확인
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createpen
CreatePen function (wingdi.h) - Win32 apps
The CreatePen function creates a logical pen that has the specified style, width, and color. The pen can subsequently be selected into a device context and used to draw lines and curves.
docs.microsoft.com
GameInfo.h
< struct CircleInfo >
- 원에 대한 정보를 저장할 구조체.
- 원은 딱 두 가지 데이터를 가지고 있다. Center(중심점), Radius(반지름)
class ColliderCircle
- Circle to Circle은 Box to Box보다 쉽다.
-- 중점과 중점을 연결한 선의 길이가 두 반지름의 합보다 작으면 충돌이다.
- HitPoint는 편의를 위해, 선의 중심점으로 해준다.
-- 사실 정확한 HitPoint는, '두 원의 교점의 중심점'이지만, 식이 매우 복잡하므로 그냥 선의 중심점으로 하는 것이 좋다. 게임은 물리 시뮬레이션이 아니므로 '그렇게 보이기만' 하면 된다.
--- 물론 정확한 교점을 구해야 하는 게임 장르들에 한해서는 구현해야 한다.
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=10baba&logNo=220732224470
[고1 수학] 두 원의 교점을 지나는 직선의 방정식(공통현의 방정식)
고1 수학 두 원의 교점을 지나는 직선의 방정식(공통현의 방정식)! 대부...
blog.naver.com
-> 요약: 두 원의 방정식을 빼서 나온 일차방정식을 둘중 하나의 원의 방정식에 대입해주면 해를 구할 수 있다.
- CColliderBox의 코드를 전부 긁어와서 일단 CColliderCircle로 바꿔주고 나머지만 수정하면 된다.
< Render() >
- 문제는 Ellipse() 함수이다. 이 함수는 속이 흰색이고 테두리가 검은색인 원을 그리기 때문에 화면을 덮어 버리게 된다.
-- 해결법은 두 가지이다.
--1. 우리가 총구를 삼각함수를 이용하여 회전시켰듯이, 이를 한 프레임에서 반복문을 돌며 360도를 돌며 선을 그리는 것이다.
--2. [ 사전 지식 ] 에서의 방법을 사용한다.
--- 반드시 SelectObject()로 펜을 교체할 때 PrevPen을 받아 두어서, 사용하고 난 뒤 다시 원래의 PEN/BRUSH로 원상복구해 주자.
//펜과 브러시를 투명하게 바꿔 준다.
HPEN PrevPen = (HPEN)SelectObject(hDC, Pen);
HBRUSH PrevBrush = (HBRUSH)SelectObject(hDC, GetStockObject(HOLLOW_BRUSH));
//...그림 그리고...
//다시 그리기 도구를 원상 복구
SelectObject(hDC, PrevPen);
SelectObject(hDC, PrevBrush);
< CircleInfo m_Info >
- CColliderBox 클래스에서 쓰던 BoxInfo와 관련된 모든 것을 CircleInfo로 변경해 준다.
< Render() >
- 여기서는 디버그 모드에서 충돌체 사이즈에 맞는 원을 그려주도록 바꿔주어야 한다.
- Ellipse() 함수를 사용한다.
- 원의 테두리 색상은 HPEN으로 변경할 수 있고,
원의 안을 투명하게 만드는 것은 GetStockObject()를 사용하여 할 수 있다.
- HPEN과 HBRUSH를 변경하여 그리고,
그리고 나서 다시 원래대로 돌려 준다.
Vector2.h
< float Distance(const Vector2& Dest) >
- 두 점 사이의 거리(피타고라스의 정리)를 구해주는 메소드를 만든다.
- 아래의 원-원 충돌여부 확인에 사용한다.
class CCollisionManager
< CollisionCircleToCircle() >
- 구조는 BoxToBox와 같다. 맨 위의 설명을 그대로 구현하면 된다.
* 제곱근(sqrtf)은 연산량이 많은 편에 속하므로, 아예 제곱근을 구하지 않은 결과끼리 비교하는 것도 괜찮다.
-> (A.Radius + B.Radius)^2 = (A.Center.x - B.Center.x)^2 + (A.Center.y - B.Center.y)^2
- 구현이 완료되었으면, CBullet과 CMonster의 충돌체를 원형으로 바꿔 주고 동작하는지 확인한다.