WinAPI 33 EventManager (3)

CJB_ny·2022년 9월 14일
0

WinAPI

목록 보기
32/79
post-thumbnail

오늘 배운거 👍👍👍

  • vector (), vector [] 선언 방법의 차이

  • ifdef _DEBUG


Delete 테스트

먼저 COjbect상속받는 애들싹다 이름 SetNameObject로 설정해주고

이름가져와서 DeleteObjectEvent에다가 이벤트 보낸다.

그리고

Func.cpp에서 해당함수를 구현해준다. AddEvent하고나면 끝!

update의 경우와 finalupdate의 경우 생각을 해보아야하는데

update의 경우에는 지금 이벤트 처리를 하면서 _vecEvents에 죽을 애들 모아놓고

바로 다음프레임에 update가 돌 것이다.

update

update돌면서 죽은애들은 update안 돌도록

죽은 경우가 아닐 경우에만 update를 돌려주도록 하자.

finalupdate

삭제될 애지만 컴포넌트들의 마지막 마무리 단계이다.

finalupdate를 마무리를 해주어야지만 작업을 마무리할 수 있다.

render

죽었는데 뭘 그리나? -> 안 그려준다.

벡터에서 뺀다.

그리고 이제 update하고 render링하고 할 수준이 아니라 다음 프레임부터는 아예 빼버려야 한다.

이벤트 처리를 해서 삭제하기 직전이 'render'부분에서 마지막 처리를 한다.

밑에 프레임 (다음 프레임)에서 이때 마무리 (벡터에서 제거)를 해주면 될 것이다.

render 수정.

이렇게 있던 내부 순환을

이렇게 바꿔준다.

주의 ❗❗❗

erase하고나서 다음을 내뱉어주니까 iter로 받는 부분 주의해라!

다음을 받으니까 알아서 내부 for문이돌아간다.

흐름 정리

이번프레임

지금 몬스터들 u -> update 개개인별로 다 돌았다. 이때까지 문제없다.

finalupdate도 다 끝났다.

그다음이제 Collisionupdate 충돌체크 남았다.

여기서 OnColiisionEnter발생했다.

-> 나 자신을 삭제해달라는 이벤트 발생햇다. c에서.

그다음 렌더링 돌고 그림 다 그렸다.

EventManager에 삭제해달라는 이벤트 등록이 되었다.

그래서 이번 프레임에서 Dead상태로 등록을 하였다.

그다음에 _vecDead에다가 넣어 놨다.

이게 한프레임 끝. (이번 프레임)

다음 프레임.

update 안돌린다.

이렇게 안돌림.

finalupdate부분까지는 살려둔다. 충돌체의 최종좌표를 잡아주기위해서

충돌체크 구현하는 부분해야지하지만 일단 돌고나서

render 하는 부분에서 아예 빼버린다.

이렇게 벡터에서 아예 빼버림.

그다음에 eventManager update돌때 _vecDead에서 Delete해버린다.

그 다음 프레임부터 아예 존재하지 않는다.

TimeManager 수정

디버그할 시 dt시간이 흘러가는것을 조절 하기위해서 수정하도록 하자.

디버그 상황일 때만 흘러가도록 특정 전처리기를 걸어 놓는 것이다.

'전처리기'는 컴파일 전에 동작을 하니까 없는셈 취급할지 있는거처럼 취급할지 결정을 한다.

확인

프젝 속성 -> 가보면은 그대로 걸려있다.

dt값이 1 / 60보다 클 경우

dt값을 1 / 60으로 보장을 하겟다라는 것이다.

디버그할 때 중간걸어놓는 시간이 길면 길 수록 막 빠르게 화면에서 움직이는 현상을 방지하기 위해서

충돌 에러 이슈 ❗❗❗

vector<int> vec(10);

vector<int> vec2[10];

이거 둘의 차이점을 숙지를 못해 발생했던 문제이다.

_objects[i].erase()가 아니라 _objects->erase(iter) 하니까 발생했던 문제이다.

미사일 Collider 문제

여전히 빨개진 상태로 올라간다...

나랑 충돌을 하고 있던애가 값자기 사라져버려서 그대로 빨간색으로 남게되는 현상을 해결해야한다,

우리가 이벤트를 받아서 한프레임 살려둔 이유가

지금 먼저 Dead상태라고 이벤트를 보낸 다음에

그 다음 프레임에서 finalupdate랑 Collider 체크를 하는 부분에서 Dead해서 없어질 녀석의 책임을 다하게 하기위해서 한프레임 살려둔 것이다.

그래서 이벤트를 보내고 다음 프레임의 Collider체크를 하는 부분까지는 살아있어야한다는 것이다.

그래서 다음 프레임의 Collider 충돌을 처리하는 과정에서 IsDead인 녀석이 있을 것인데

이녀석을 처리할 부분을 구현을 해주었어야 했다.

충돌 검사 (ColliderManager)

ColliderManager의 이 함수가 충돌을 검사하는 함수이다.

지금 이부분에서 Collider가져와서 두 충돌체의 조합 ID를 생성하고있다.

if->second 들어와서 보면은 둘중 하나가 삭제될 예정일 수 있다.

그렇다면 80번째 if문에 들어왔을 때 이제 삭제될 예정이니까 OnCollisionExit를 해주어야 하지 않을까??

조금 애매한 상황?

93번째 else일 경우가 어떤 상황이냐면은

현재 충돌중인데 이전에는 충돌하지 않은 경우이다.

하필 내가 삭제될려고하는 그 순간에 충돌이 되었다라는 상황이다.

=> 그렇다면 그냥 아무 처리도 해주지 말자는 것이다.

둘중 하나가 삭제 예정이라면은, 충돌하지 않은 것으로 취급한다.

이렇게 둘다 => '&&' 삭제 예정이 아닐 경우에만 이벤트 처리를 해주도록 하자.

	for (size_t i = 0; i < vecLeft.size(); ++i)
	{
		// 충돌체를 보유하지 않는 경우
		if (nullptr == vecLeft[i]->GetCollider())
			continue;

		for (size_t j = 0; j < vecRight.size(); ++j)
		{
			// 충돌체를 보유하지 않는 경우 || 나 자신일 경우
			if (nullptr == vecRight[j]->GetCollider() || vecLeft[i] == vecRight[j])
				continue;
			
			Collider* leftCollider = vecLeft[i]->GetCollider();
			Collider* rightCollider = vecRight[j]->GetCollider();

			// 두 충돌체 조합 아이디 생성
			COLLIDER_ID id;
			id._leftID = leftCollider->GetID();
			id._rightID = rightCollider->GetID();

			// auto iter = _mapCollisionInfo.find(id.ID);
			iter = _mapCollisionInfo.find(id.ID);

			// 충돌 정보가 미 등록 상태인 경우 등록 (충돌하지 않았다 로)
			if (_mapCollisionInfo.end() == iter)
			{
				_mapCollisionInfo.insert(make_pair(id.ID, false));
				iter = _mapCollisionInfo.find(id.ID);
			}
			
			// 진짜 충돌 검사
			if (IsCollision(leftCollider, rightCollider))
			{
				// 현재 충돌 중이다.

				if (iter->second)
				{
					// 이전에도 충돌하고 있었다. Stay

					// 둘중 한놈 Delete예정일 수 있다.
					if (vecLeft[i]->IsDead() || vecRight[j]->IsDead())
					{
						// 둘중하나가 삭제 예정이라면은, 충돌을 해제시켜준다.
						leftCollider->OnCollisionExit(rightCollider);
						rightCollider->OnCollisionExit(leftCollider);
						iter->second = false;
					}
					else
					{
						// 삭제될 예정이 아닐 경우
						leftCollider->OnCollisonStay(rightCollider);
						rightCollider->OnCollisonStay(leftCollider);
					}
				}
				else
				{
					// 이전에는 충돌하지 않았다. (딱 처음 충돌한 경우) Enter

					if (!(vecLeft[i]->IsDead()) && !(vecRight[j]->IsDead()))
					{
						// 둘중하나가 삭제 예정이라면은, 충돌 하지 않은것으로 취급
						leftCollider->OnCollisionEnter(rightCollider);
						rightCollider->OnCollisionEnter(leftCollider);
						iter->second = true;
					}

					// 일로오면은 그냥 충돌은 없었던 것이다.
					
				}
			}
			else
			{
				// 현재 충돌중 이지 않다.

				if (iter->second)
				{
					// 이전에는 충돌하고 있었다. Exit
					leftCollider->OnCollisionExit(rightCollider);
					rightCollider->OnCollisionExit(leftCollider);
					iter->second = false;
				}
			}
		}
	}

충돌 검사하는 for문은 대강 이런식이 될 것이다.

5대 맞고 뒤지기에러

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

0개의 댓글