게임 화면을 출력하는 것은 Scene이 포함하고 있는 모든 Object를 Render하는 것과 같다. 그래서 실질적인 게임화면의 출력은 Object::Render에서 이루어진다.
POSITION tPos = m_tPos - m_tSize * m_tPivot;
tPos -= GET_SINGLE(CCamera)->GetPos();
RESOLUTION tClientRS = GET_SINGLE(CCamera)->GetClientRS();
bool blnClient = true;
if (tPos.x + m_tSize.x < 0)
blnClient = false;
else if (tPos.x > tClientRS.iW)
blnClient = false;
else if (tPos.y + m_tSize.y < 0)
blnClient = false;
else if (tPos.y > tClientRS.iH)
blnClient = false;
blnClient는 클라이언트 화면 (사용자에게 보여지는 화면) 내의 Object만 Render한다. 이것은 최적화에 중요한 부분인데,
화면에 나오지 않는 Object를 계속 출력하면 프로그램 성능과 FPS에 큰 영향을 미친다.
if (m_pTexture&&blnClient)
{
POSITION tImagePos;
if (m_pAnimation)
{
PANIMATIONCLIP pClip = m_pAnimation->GetCurrentClip();
if (pClip->eType == AT_ATLAS)
{
tImagePos.x = pClip->iFrameX * m_tSize.x;
tImagePos.y = pClip->iFrameY * m_tSize.y;
}
}
tImagePos += m_tImageOffset;
if (m_pTexture->GetColorKeyEnable())
{
TransparentBlt(hDC, tPos.x, tPos.y, m_tSize.x,
m_tSize.y, m_pTexture->GetDC(), tImagePos.x,tImagePos.y,
m_tSize.x, m_tSize.y, m_pTexture->GetColorKey());
}
else
{
BitBlt(hDC, tPos.x, tPos.y, m_tSize.x, m_tSize.y,
m_pTexture->GetDC(), tImagePos.x, tImagePos.y, SRCCOPY);
}
}
Object가 자신의 Texture을 가지고 있고 클라이언트 화면 내에 있다면 Render을 진행한다. 텍스쳐가 배경색을 지워야 하는 텍스쳐라면 (ColorKeyEnable이 true라면) TransparentBlt 함수를 이용해 배경색을 지워 출력한다.
BOOL TransparentBlt
(이미지 출력할 핸들, 이미지 출력 위치 x, 이미지 출력 위치 y, 이미지 출력 크기 x, 이미지 출력 크기 y, 이미지의 핸들, 이미지 시작 지점 x, 이미지 시작 지점 y, 잘라낼 이미지 크기 x, 잘라낼 이미지 크기 y, 투명하게 할 RGB 색상);
ColorKeyEnable이 false라면 이미지 그대로 출력한다.
BOOL BitBlt
(이미지 출력할 핸들, 이미지 출력 위치 x, 이미지 출력 위치 y, 이미지 출력 크기 x, 이미지 출력 크기 y, 이미지의 핸들, 이미지 시작 지점 x, 이미지 시작 지점 y, 이미지 출력방법 - SRCCOPY는 원본이미지 그대로 출력 );
그렇다면 Object의 m_pTexture은 어떤 과정으로 설정하는 것일까?
void CObj::SetTexture(const string& strKey, const wchar_t* pFileName, const string& strPathKey)
{
SAFE_RELEASE(m_pTexture);
if (pFileName)
m_pTexture = GET_SINGLE(CResourcesManager)->LoadTexture(
strKey, pFileName, strPathKey);
}
Object::SetTexture은 Texture 이름, 파일명, 경로를 입력받는다. 경로는 설정 안할 시 디폴트로 TEXTURE_PATH로 텍스쳐가 저장되어 있는 곳으로 자동 설정된다. 그리고 ResourcesManager의 LoadTexture을 호출한다.
CTexture* CResourcesManager::LoadTexture(const string& strKey,
const wchar_t* pFileName, const string& strPathKey)
{
CTexture* pTexture = FindTexture(strKey);
if (pTexture)
return pTexture;
pTexture = new CTexture;
if (!pTexture->LoadTexture(m_hInst, m_hDC, strKey, pFileName, strPathKey))
{
SAFE_RELEASE(pTexture);
return NULL;
}
pTexture->AddRef();
m_mapTexture.insert(make_pair(strKey, pTexture));
return pTexture;
}
ResourcesManager의 m_mapTexture에 해당 Texture가 있으면 반환하고 없으면 새로 Texture을 생성해 map에 추가한다. 추가 전에 Texture::LoadTexture을 실행한다.
bool CTexture::LoadTexture(HINSTANCE hInst, HDC hDC,
const string& strKey, const wchar_t* pFileName,
const string& strPathKey)
{
m_strFileName = pFileName;
m_strKey = strKey;
m_strPathKey = strPathKey;
//메모리 DC만들어줌
m_hMemDC = CreateCompatibleDC(hDC);
//전체 경로
const wchar_t* pPath = GET_SINGLE(CPathManager)->FindPath(strPathKey);
wstring strPath;
if (pPath)
strPath = pPath;
strPath += pFileName;
m_hBitmap = (HBITMAP)LoadImage(hInst, strPath.c_str(),
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
//위에서 만들어준 비트맵 도구를 DC에 지정한다
//지정할 때 반환되는 값은 DC에 기본으로 지정되어 있던 도구
m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
GetObject(m_hBitmap, sizeof(m_tInfo), &m_tInfo);
return true;
}
m_hMemDC는 Texture가 가지고 있는 DC이다. CreateCompatibleDC로 생성하는데 출력장치와 연결되지 않은 DC를 생성한다. 이 DC와 연결된 비트맵 객체에 그림이 그려지지만 화면에 출력되지 않는 DC를 Memory DC라고 한다. CreateComptibleDC는 hDC 핸들을 인수로 갖는데 이 핸들과 호환(Compatible)되는 DC를 만든다. hDC와 호환된다는 것은 hDC가 화면을 출력하는 것과 동일한 방식으로 MemDC와 연결된 비트맵에 그리게 된다는 것이다.
그리고 LoadImage를 이용해서 비트맵 도구를 만들고 m_hBitmap에 저장한다. 그리고 만든 비트맵 도구를 사용하기 위해 SelectObject로 메모리 DC에 지정한다. 반환되는 값은 DC에 기본으로 지정되어 있던 도구이므로 m_hOldBitmap에 저장한다. 마지막으로 m_hBitmap으로 비트맵의 정보를 GetObject로 m_tInfo에 저장한다.
'WinAPI' 카테고리의 다른 글
| [WinAPI] 게임 프레임워크 - 8. Animation (0) | 2022.02.03 |
|---|---|
| [WinAPI] 게임 프레임워크 - 7. Collision (0) | 2022.02.03 |
| [WinAPI] 게임 프레임워크 - 5. PathManager, 유니코드와 멀티바이트 (0) | 2022.02.02 |
| [WinAPI] 게임 프레임워크 - 4. Input (0) | 2022.02.02 |
| [WinAPI] 게임 프레임워크 - 3. Reference Count (0) | 2022.02.01 |