프로그래밍/Win32 API

##3. 충돌체크 / 추상팩토리패턴 / 컨테이터 순차접근 / 문자열출력

hscho00 2020. 8. 17. 12:30

 


LateUpdate()

 

모든 개체의 Update()를 완료 후, 변경된 값을 토대로

상태를 변경할 필요가 있을 때 사용


RECT 충돌체크

BOOL IntersectRect(
  LPRECT     lprcDst,
  const RECT *lprcSrc1,
  const RECT *lprcSrc2
);

 

원형 충돌체크

두 중심 사이의 거리가 두 반지름의 합보다 작으면 충돌

bool CCollisionMgr::CheckCircle(const CObj& _obj1, const CObj& _obj2)
{
	float fX = abs(_obj1.Get_Info().fX - _obj2.Get_Info().fX);
	float fY = _obj1.Get_Info().fY - _obj2.Get_Info().fY;
	
	float fRad = (float)((_obj1.Get_Info().iWidth + _obj2.Get_Info().iHeight) >> 1);

	if (fRad * fRad > fX * fX + fY * fY)
		return true

	return false;
}


CollisionMgr

// CCollisionMgr.h
// ...
class CCollisionMgr
{
public:
	CCollisionMgr();
	~CCollisionMgr();

public:
	static void SetDead_Rect(vector<CObj*>& _v1, vector<CObj*>& _v2);
	static void SetDead_Circle(vector<CObj*>& _v1, vector<CObj*>& _v2);

private:
	static bool CheckCircle(const CObj& _obj1, const CObj& _obj2);

};
// CCollisionMgr.cpp
// ...
void CCollisionMgr::SetDead_Rect(vector<CObj*>& _v1, vector<CObj*>& _v2)
{
	RECT rc = {};

	for (auto& obj1 : _v1)
	{
		if (obj1->IsDead())
			continue;

		for (auto& obj2 : _v2)
		{
			if (obj2->IsDead())
				continue;

			if (IntersectRect(&rc, &obj1->Get_Rect(), &obj2->Get_Rect()))
			{
				obj1->Set_Dead(true);
				obj2->Set_Dead(true);
			}
		}
	}
}

void CCollisionMgr::SetDead_Circle(vector<CObj*>& _v1, vector<CObj*>& _v2)
{
	for (auto& obj1 : _v1)
	{
		if (obj1->IsDead())
			continue;

		for (auto& obj2 : _v2)
		{
			if (obj2->IsDead())
				continue;

			if (CheckCircle(*obj1, *obj2))
			{
				obj1->Set_Dead(true);
				obj2->Set_Dead(true);
			}
		}
	}
}
// CMainGame.cpp
//...
void CMainGame::LateUpdate()
{
	CCollisionMgr::SetDead_Rect(m_vecObj[OBJ::ID::MONSTER], m_vecObj[OBJ::ID::BULLET]);

	for (int i = 0; i < OBJ::ID_END; ++i)
	{
		for (auto& pObj : m_vecObj[i])
		{
			if (pObj->IsDead())
				continue;

			pObj->LateUpdate();
		}
	}

	// ...
}

추상 팩토리 패턴

 

구체적인 클래스에 의존하지 않고 서로 연관되거나 의존적인 개체들의 조합을 만드는 인터페이스를 제공하는 패턴

> 관련성 있는 여러 종류의 개체를 일관된 방식으로 생성하는 경우에 유용

> 생성 방법을 알고 있는 개체를 매개변수를 넘겨받음으로써 생성할 개체의 유형을 달리한다

 

// AbstractFactory.h
#pragma once

class CObj;

template<typename T>
class CAbstractFactory
{
public:
    static CObj* Create()
    {
        CObj* pObj = new T;
        pObj->Init();

        return pObj;
    }

    static CObj* Create(float _x, float _y)
    {
        CObj* pObj = new T;
        pObj->Init();
        pObj->Set_Pos(_x, _y);

        return pObj;
    }
};


// MainGame.cpp
// ...
void CMainGame::Init()
{
    // ...
    CObj* pPlayer = CAbstractFactory<CPlayer>::Create();
    
    // ...
}

여기서는 생성 방법을 알고 있는 개체(Factory)를 만들지 않고 간단하게 매개변수를 통해서만 구분하였음


컨테이너 순차 접근

// MainGame.h
// ...
vector<CObj*>	m_vecObj[OBJ::ID_END];


// MainGame.cpp
//...
void CMainGame::Update()
{
    for (int i = 0; i < OBJ::ID_END; ++i)
    {
        for (auto& pObj : m_vecObj[i])
        {
            pObj->Update();
        }
    }
}

문자열 출력

 

BOOL TextOutA(
  HDC    hdc,
  int    x,
  int    y,
  LPCSTR lpString,
  int    c
);

// MainGame.cpp
// ...
void CMainGame::Render()
{
    // ...
    TCHAR szBuff[16] = L"";
    swprintf_s(szBuff, L"Bullet: %d", m_iBulletAliveCnt);
    TextOut(m_hDC, 50, 50, szBuff, lstrlen(szBuff));
    
    // ...
}