WinAPI 28 Collider (4)

CJB_ny·2022년 9월 9일
0

WinAPI

목록 보기
27/79
post-thumbnail

오늘 배운거 👍👍👍

  • 비트 연산자

  • 비트 빼주기

  • vector [] 를 활용한 반쪽짜리 메트릭스 이용하기

  • map을 통한 이전 프레임의 충돌정보 저장 및 사용하기


비트 연산자 ❗❗❗

이때까지 거의 사용해본적 없다가 이제 사용한다!

기억이 잘 안남! or and말고!

만약 비트가 같다면은 켜주던가 꺼주던가 해아하는데

비트 빼주기 ❗❗❗

지금 생각나는게 '~'인데 이전에 했던 부분이

https://velog.io/@starkshn/CPP%EC%96%B4%EC%86%8C11%EB%B9%84%ED%8A%B8-%EC%97%B0%EC%82%B0%EC%9E%902

비트를 빼주는 부분

a &= ~b;

이렇게 비트를 빼버리면 된다.

그래서 Enter 부분에서 그룹끼리 충돌로 비트를 켜주는 작업 해준다음에

이제 colliderManager의 update부분에서 실제로 물체끼리 충돌을 했는지 안했는지 확인해야한다.

비트 검사

32줄의 행을 검사를 하면서 열도 32번 검사를 해야하는데

(이까지 ㅇㅋ?)

이렇게 햇을 때 문제점 있음.

한 행 접근할 때마다 모든 비트 싹다 검사를 하겠다는 말이다.

그런데 지금 우리가

진행하면 진행할 수록 검사하는 비트가 하나씩 줄어 듦.

비트를 왼쪽으로 밀어서 검사를 할 것이라서

그래서 이렇게 if문으로 체크를 해주어야 한다~

만약 1번 3번 그룹에 if문 안에 걸렸다면은

지금 row, col값이 몇이여야 하나?

row = 1, col = (1 << 3) (= 8)

값 다 잘들어오는 것 확인했다.

이제 진짜 충돌 진행을 해야한다.

현재 씬에 있는 오브젝트들 중에 알맞는 두 그룹을 가져온다.

오브젝트 가져오기

충돌을 했다면 이제 CollisionGroupUpdate를 호출하여 현재 씬에 있는 오브젝트를 달라고 요청해서 가져와야한다.

우리가 left, right로 준 해당하는 그룹의 오브젝트를 가져 와야한다.

현재 Scene에 있는 오브젝트들은 _objects라는 벡터가 관리를 하는중이다.

그룹에 지정된 벡터를 받아 와야한다.

그래서 이런 함수를 만들어주는데 지금 반환 타입이

vector < CObject* > 이면은 될까?

이렇게하면은 '원본'이 반환되는 것이 아니라 벡터가 복사가 될 것이다.

주소를 전달을 해주게 되니까.

(아무튼 원본이 반환되는 형식은 아니다)

그래서 참조로 이렇게 주어야 하지 않을까?

그런데 또! 그냥 레퍼런스로 준다면은 문제가 있지 않을까?

그냥 충돌검사만 하려고 했을 뿐인데 말이다.

이렇게 해주도록 하자. 인자로 const붙인것은 그냥 내가 붙인것이다.

CScene에서는 GetGorupObjects라는 함수를 파주고

ColliderManager에서는 SceneManager에 접근을 하여 현재 씬이 무엇인지 얻어오고

현재씬 -> GetGroupObjects를 호출을해서 해당그룹에 해당하는 오브젝트들을 가지고 온다.

그런데 여기서 조금 문제가 있다.

이렇게 받아왔는데 이거 두개 벡터 지금 '지역변수' 아니냐?

참조를 줬으니까 ❓❓❓

많이 하는 착각중에 하나가

이렇게 vecLeft, vecRight로 참조값을 받았는데

GetGroupObjects가 참조를 반환하니까 지금 두 벡터가 '원본'이라고 생각을 한다.

(내 생각은 원본이 아니라 원본의 또 다른 이름이라고 어느정도 받아 들이고있다. 대신 원본의 또 다른 이름이니까 어떻게보면 원본이고...)

지역변수

그러면

vecLeft, vecRight를 수정을 하면은 원본이 '수정'이 되나?

절대 아니다.

GetGroupObjects가 반환하는것이 '원본'이지

지금

vector<CObject*> vecLeft(Right) = GetGroupObjects(); 

이것은

이렇게 vecLeft같은 애들은 지역변수로 원본을 '복사받은'은 벡터이다.

그래서 ❗❗❗

원본을 받고싶다면은 우리가 기초 개념을 다시 생각해보면은

레퍼런스로 받고 싶다하면은

vector< CObject* > vecLeft가 아니라 받을 변수의 타입도 '레퍼런스'이여야 한다.

그런데 지금 GetGroup함수가 반환타입이 const ref니까 맞춰 주어야한다.

레퍼런스 사용이유 ❗

우리가 이런식으로 ColliderManager의ㅡ CollisionUpdate에서 vecLeft와 같은 벡터에게 데이터를 줄 때

'복사 비용'을 줄이기 위해서 GetGroupObjects 함수의 반환 타입을 레퍼런스로 하였고

vecLeft도 데이터를 받을 때 '복사비용'을 줄이기 위해서 레퍼런스로 받는것이다.

숙지 ㄱㄱ.

이렇게 해줄 경우 같은 그룹일 수도있다.

자기 자신이랑 충돌하는 경우 방지해야한다.

또한 충돌체가 없는 오브젝트의 경우 충돌체 검사를 하면 안된다.

vecLeft[i]랑 vecRight[0~END]까지 싹다 비교해야함.

그런데 충돌체없는 경우가 있을 수 있기 때문에

이렇게 i번재가 충돌체가 없다면은 건너뛰고

충돌당하는 애가 충돌체가 없을 경우 또 건너 뛰어준다.

그래서

진짜 충돌 처리하는 IsCollision만들어주고 해당함수에

이따위로 인자를 넣어주면 된다.

정리

시발 복잡하고 힘들다 잠깐 정리하도록 하자.


ColiiderManager를 현재 Scene에서 매프레임 호출 할 것이다.

그러면 해당함수 호출되면서 현재 씬에있는 모든 오브젝트를 행과 열로

반페이지만을 짤라서 비트 연산자로 확인을 한다음에

CollsitionGroupUpdate함수의 인자로 left, right를 받아와서

현재씬의 해당 left, right의 그룹에 맞는 벡터를 참조로(원본을)가지고 와서

이중 for문으로 각기 벡터가 충돌체를 가지는지 안가지는지 확인을 다 끝낸다음에

진짜 충돌 검사인 IsCollision함수를 호출한다.

여기서부터 이제 진짜 두 물체가 충돌체를 가지고 있다고 판단이 되는 부분이니까

이제부터는 충돌체의 크기를 계산을해서 실제로 충돌했을 때 어떻게 해야할지 구현을 해주어야한다.

이전프레임 정보 ❗❗❗

현재 이상태로는 OnCollisionEnter, Stay, Exit인지 구분하기 힘들다.

그래서 '이전 프레임'의 정보가 필요하다.

그래서 ColliderManager는 이전 프레임의 충돌 정보를 가지고 있어야한다.

그런데, 지금 이전 프레임의 정보가 좀 방대하다.

물체가 100개가 있다고 하더라고 조합가능한 경우의 수가

99~1, 98~1, 97~1 ... 이런식인데 우리는 탐색을 엄청나게 빠르게 해아한ㄷ.

'탐색'에 특화되어 있는 자료구조가 map이 있을 것이다.

map보다 더 빠른게 해쉬테이블, 해쉬 맵

(벡터 써도 되지 않나...?)

map 사용 (이전 프레임) ❗

우리는 map사용한다.

키값으로는 절대 다른 충돌체간의 조합으로는 흉내낼 수 없는 값으로 하고

딱 두 충돌체 이여야만 나오는 키값이 필요하다.

value값으로는 이전 프레임의 데이터가 들어가 있어야한다.

절대 곂치지 않는 키값?

충돌체들한데 id값을 주도록 하자.

그렇다면 Collider의 멤버 변수로 정적멤버 변수를 하나 만들어주고

이 녀석은 멤버로 포함되어 지지않고 데이터 영역에 올라가니까

Collider 생성자를 호출할 때마다 이 정적 멤버 변수의 값을 ++ 해주도록 하자.

그러면 Collider를 가지는 녀석들의 ID값은 절대 곂칠 수 없게 될 것이다.

정적 멤버 변수 (복습) ❗❗

이렇게 멤버 변수로 들어가지는 않으니까 항상 클래스 밖에서 초기화를 해주어야하고

초기화 작업 = 0; 부분이 딱 한번밖에 실행이 되지 않는다.

Collider객체가 생성될 때마다 _id를 증가 시켜서 g_ID를 늘려준다.

그래서 생성자 부분에서 생성자가 호출이 되면은

멤버 변수인 _id를 g_id++한 값으로 초기화를 해주어서 멤버변수로 넣어주도록 하자.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글