*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
[ 변경 사항 ]
class CWidgetWindow
{ m_Pos -> m_PosLT }
- 이 클래스의 위치 변수는 창 좌측 상단의 위치를 저장하는데, 여타 클래스들의 m_Pos와 똑같이 써 버리면 혼동이 올 수도 있을 것 같아 m_PosLT로 변수 이름을 변경하였음.
class CScene;
< Update, PostUpdate, Render >
- m_Visibility 변수와 관련 기능을 제거하고, 대신 CRef에 잡혀 있는 m_Enable 변수를 사용한다.
-- 둘은 정확히 똑같은 기능을 하기 때문에, 굳이 같은 기능을 또 만들 필요는 없다.
- 지난 번에 m_Active(false가 되면 완전 제거)와 m_Enable(잠시 비활성화)에 대한 처리를 해주지 않았었다.
-- 이 처리 과정도 추가해 준다.
< static bool SortWidget(const CSharedPtr<CWidgetWindow>& Src, const CSharecPtr<CWidgetWindw>& Dest) >
- 위젯의 렌더링 순서를 정렬하기 위한 메소드
- m_ZOrder를 받아와서 값을 비교하여 반환한다.
< PostUpdate() >
- 위젯 윈도우에 대한 PostUpdate()를 진행하기 전에, 만약 CWidgetWindow 클래스가 2개 이상이라면 Zorder에 대해 내림차순으로 정렬을 해 준다.
- 정렬하고 순회를 돌며 CWidgetWindow::PostUpdate()를 호출해 주고, 만약 여기서 제거(Active false)되거나 스킵(Enable false)되지 않았으면 해당 CWidgetWindow를 충돌 검사 대기열에 넣어준다(m_vecWidgetWindow).
< Render() >
- 아까 PostUpdate()에서 내림차순으로 정렬했으므로,
reverse_iterator를 통해 역순으로 순회를 돌아주면 오름차순으로 출력이 될 것이다.
- 그럼 ZOrder이 높은 게 나중에 그려질 것이고, 그럼 화면 가장 위에 출력되게 된다.
class CSceneCollision;
{ std::vector<class CWidgetWindow*> m_vecWidgetWindow }
< void AddWidgetWindow(CWidgetWindow* Window) >
- 씬 충돌 클래스에서도 위젯윈도우의 정보를 들고 있는다.
-- CCillider*을 매 프레임마다 m_vecCollider 안에 추가하여 충돌검사를 하고, 검사를 다 하면 다시 비워줬던 것과 똑같은 방법으로 검사하기 위함이다.
- CScene::PostUpdate() 메소드에서 각 위젯 윈도우의 PostUpdate()가 끝나면, 여기에 추가하여 충돌 검사 대기열에 넣어놓는다.
< bool SortWidget(CWidgetWindow* Src, CWidgetWindow* Dest) >
- 여기도 위와 마찬가지로 충돌검사를 하기 전 정렬을 해주기 위해 이 메소드를 만든다.
다만, 여기는 숫자가 높은 순부터 충돌검사를 해야 하므로 내림차순으로 정렬해주어야 한다.
< void CollisionUpdateMouse() >
- 마우스와 충돌하는 물체는 어떤 상황에서든 단 하나이다.
-- 단 하나이므로, UI에서 충돌했을 때도 충돌 중인 게임오브젝트가 없었는지 확인해야 하며, 게임오브젝트와 충돌했을 때도 충돌중인 UI가 없었는지 확인해야 한다.
-- 이 메소드 안에서 UI와 마우스의 충돌을 먼저 검사한다. 만약 충돌하는 UI가 있었을 경우, 이후 과정은 전부 스킵하고 마지막 단계에서 배열을 비워주기만 하면 된다.
--- 마지막 단계에서 배열을 비워주는 과정을 반드시 거쳐야 하므로 return을 쓰면 안된다!!
- 게임오브젝트는 마우스의 월드 위치(게임 안의서의 좌표)와 충돌처리를 하는 반면, UI는 창의 크기 안에서만 충돌 처리가 진행된다. 좌표 전달할 때 주의할 것.
[ 충돌 순서 ]
1.마우스의 창 위에서의 좌표값을 받아놓고, UI 충돌검사 때 충돌이 확인되면 이후 과정을 스킵하기 위한 bool 변수도 하나 선언하고 false로 초기화한다.
2. UI 충돌을 먼저 검사한다. UI 배열의 경우 삽입 시점에 Zorder 기준으로 내림차순 정렬이 되어 있으므로 단순 순회만 돌아주면 된다.
3. 순회를 돌면서 충돌을 검사한다. 충돌 검사 메소드에서는 위젯의 주소를 요구하므로 임시 변수를 만들어 nullptr로 초기화한 뒤 전달한다.
4. 만약 충돌임이 확인되면, 방금 만든 변수에 충돌한 위젯의 주소가 반환되었을 것이다.
5. 만약 기존의 충돌중인 위젯이 있고(m_MouseCollidingWidget) (&&) 이 충돌중인 위젯 주소가 방금 받아온 주소와 다르다면, 기존에 충돌중이던 위젯의 충돌이 끝났다는 이야기이다. 기존에 충돌중이던 위젯의 충돌 종료 함수를 호출해 준다.
6. 또한 충돌중인 '게임오브젝트'가 있었다면, 해당 주소의 충돌 종료 함수를 호출하고 주소를 제거한다.
7. 충돌중인 위젯을 저장하는 변수에 새로 충돌한 위젯의 주소를 등록하고, 이후 과정은 스킵할 수 있게 Skip 변수를 true로 바꿔준다.
8. 이후 게임오브젝트의 충돌 검사는 Skip 변수가 false일때만 진행한다.
9. 만약 게임오브젝트의 충돌 검사 단계에 들어갔을 경우, 어떤 UI와도 충돌하지 않았다는 뜻이 된다.
만약 충돌중이던 UI가 있을 경우, 충돌 종료 함수를 호출하고 주소를 제거한다.
10. 이후 게임오브젝트 충돌검사를 하고,
11. 끝났으면 UI와 게임오브젝트 배열 모두 비워준다.
{ class CWidget* m_MouseCollisionWidget }
- 위젯 윈도우 안의 개별 위젯을 포인터로 들고, 충돌 처리를 하기 위한 변수.
< void CollisionUpdate() >
- 가장 마지막 단계에서 m_vecCollider처럼 clear() 함수를 통해 싹 비워준다.
class CWidgetWindow;
< bool CollisionMouse(CWidget** WidgetAddr, const Vector2& Pos) >
- 여기서는, 충돌할 개별 CWidget이 있었을 경우 해당 주소를 담아서 반환할 수 있도록 CWidget 클래스의 이중 포인터를 인자로 추가한다.
- 첫 번째로, 위젯윈도우와 충돌검사(사각형)를 한다. 검사 로직은 사각형 충돌체 - 점 검사로직과 똑같다.
여기서 통과하지 못했다면 false를 반환하고,
여기를 통과했다면 개별 CWidget들을 순회 돌며 충돌 확인 메소드를 호출해서 검사한다.
만약 충돌하는 위젯이 있었을 경우 이중 포인터에 충돌한 위젯의 주소를 저장하고, true를 반환한다.
class CWidget
< bool CollisionMouse(const Vector2& Pos) >
- 마지막으로, 개별 위젯과 마우스의 충돌 검사를 하는 메소드.
- 마찬가지로 점 - 사각형 충돌 로직을 통해 충돌을 확인하고,
첫 충돌이라면 충돌 시작 콜백함수를 호출한다.
충돌 종료 콜백함수는 CSceneCollision 클래스에서 다른 충돌체와의 충돌 여부 확인 후 호출되고 있으므로 여기서 해줄 필요가 없다.
class CButton
- 콜백 함수에 진입했을 때 ButtonState를 바꿔 준다.
렌더링 때 ButtonState에 따라 다르게 출력되는 함수는 이미 구현되어 있으므로 딱히 건드릴 필요가 없다.
< 구현 결과 >
'WIN32API FrameWork > 한단계씩 직접 구현' 카테고리의 다른 글
59. 마우스에 애니메이션 띄우기 (0) | 2022.06.07 |
---|---|
58. 버튼 완성 (0) | 2022.06.07 |
56. 위젯 (0) | 2022.06.06 |
55. 사운드 (0) | 2022.06.03 |
54. 마우스 충돌 - 픽셀 충돌 (0) | 2022.06.03 |