1. 미사일 발사 디버깅 ;  for 문에서 데이터 추가 문제

미사일을 발사하고 objects 벡터에 미사일이 추가되는 순간 크래시가 발생하는 것을 알 수 있다.

for 문에서 범위 기반 순회를 할 때, 새로운 요소가 추가되면 순서가 꼬이게 된다.

 

 

1) objects 벡터를 참조가 아니라 복사로 받기

요소를 복사로 받으면 원본을 수정하는 데에 어려움이 있으나, 단순히 추가하는 것은 큰 문제가 되지 않는다.

따라서 GameScene.cpp에서 아래의 코드처럼 참조 연산자를 제거한다.

void GameScene::Update()
{
	//if (_player)
	//	_player->Update();
	const vector<Object*> objects = GET_SINGLE(ObjectManager)->GetObjects();
	for (Object* object : objects)
		object->Update();
}

 

2) 미사일 투사체의 소멸은 어디에서?

미사일이 화면 밖으로 벗어났을 때 삭제되도록 한다.

void Missile::Update()
{
	float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();

	_pos.y -= deltaTime * _stat.speed;

	// *주의!
	if (_pos.y < -200)
	{
		GET_SINGLE(ObjectManager)->Remove(this);
		return;
	}

* 객체를 삭제(delete)했다면 즉시 return한다. delete 이후 포인터가 유효하지 않은 메모리 주소를 가리키고 있기 때문이다.

** 혹은 스마트 포인터를 사용하도록 한다.

 

 

2. 몬스터 만들기

void Monster::Render(HDC hdc)
{
	Utils::DrawRect(hdc, _pos, 50, 50);
}

이어서 GameScene에서 몬스터를 5마리 만든다.

	for (int32 i = 0; i < 5; i++)
	{
		Monster* monster = GET_SINGLE(ObjectManager)->CreateObject<Monster>();
		monster->SetPos(Pos{( i + 1) * 100, 100 });
		GET_SINGLE(ObjectManager)->Add(monster);
	}

다만 여기에서 캐스팅 오류가 발생하는데, 기본적으로 Pos는 float이고, 여기에서는 int로 사용하려고 하기 때문에 축소 변환이 발생하기 때문이다.

따라서 해당 부분을 static_cast로 캐스팅해준다.

monster->SetPos(Pos{static_cast<float>(( i + 1) * 100), 100 });

 

 

3. 충돌 판정 만들기

void Missile::Update()
{
	float deltaTime = GET_SINGLE(TimeManager)->GetDeltaTime();

	_pos.y -= deltaTime * _stat.speed;

	// 충돌
	const vector<Object*>& objects = GET_SINGLE(ObjectManager)->GetObjects();
	for (auto object : objects)
	{
		if (object == this)
			continue;

		// player가 발사한 미사일인가?
		if (object->GetObjectType() != ObjectType::Monster)
			continue;

		Pos p1 = GetPos();
		Pos p2 = object-> GetPos();

		const float dx = p1.x - p2.x;
		const float dy = p1.y - p2.y;
		float dist = sqrt(dx * dx + dy * dy);

		if (dist < 25)
		{
			// 안전성 확인되지 않음
			GET_SINGLE(ObjectManager)->Remove(object);
			GET_SINGLE(ObjectManager)->Remove(this);
			return;
		}
	}

	// 맞지 않고 창을 벗어났다면 delete
	if (_pos.y < -200)
	{
		GET_SINGLE(ObjectManager)->Remove(this);
		return;
	}
}

object들의 정보가 담긴 벡터를 인스턴스를 사용하여 꺼내온다.

이후에 오브젝트를 하나씩 순회하면서 미사일이라면 스킵, player가 발사한 미사일인지 체크를 해주면

스킵되지 않은 요소들은 모두 몬스터일 것이다.

이어서 미사일의 위치를 p1, 몬스터의 위치를 p2에 GetPos로 받아온다.

둘의 거리 차이를 피타고라스 방정식으로 계산하고, 미사일과 대상의 거리가 가까우면 둘 다 Remove 해준다.