프로그래밍/Win32 API
##8. 비트맵 / 더블 버퍼링 / FSM / 스프라이트 / Scene 전환
hscho00
2020. 9. 15. 19:54
Bitmap
void CBitmap::Load_Bitmap(const TCHAR* _pFilename)
{
HDC hDC = GetDC(g_hWnd);
m_hMemDC = CreateCompatibleDC(hDC);
ReleaseDC(g_hWnd, hDC);
m_hBitmap = (HBITMAP)LoadImage(NULL, _pFilename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap);
}
void CBitmap::Release()
{
SelectObject(m_hMemDC, m_hOldBitmap);
DeleteObject(m_hBitmap);
DeleteDC(m_hMemDC);
}
더블 버퍼링(Double Buffering)
비트맵을 화면에 뿌려줄 때, 계속해서 그리는 작업을 반복하기 때문에 깜빡이는 현상이 나타남
이 현상을 해결하기 위해 더블버퍼링을 사용해야 함
매번 출력 내용을 화면에 바로 그리지 않고,
빈 비트맵 위에 출력해야 할 모든 비트맵을 그린 다음, 한번에 출력한다.
void CMainGame::Render()
{
HDC HBackBuffer = g_BitmapMgr->FindOrNull(L"BackBuffer");
g_SceneMgr->Render(HBackBuffer);
BitBlt(m_hDC, 0, 0, WINWIDTH, WINHEIGHT, HBackBuffer, 0, 0, SRCCOPY);
// ...
}
Finite State Machine (유한 상태 기계)
자신이 취할 수 있는 유한한 갯수의 상태들을 가진다.
그 중에서 반드시 하나의 상태만을 취한다.
현재 상태는 특정 조건이 되면 다른 상태로 변할 수 있다.
Sprite
// Struct.h
// ...
typedef struct tagFrame
{
int iFrameStart;
int iFrameEnd;
int iFrameScene;
DWORD dwFrameTime;
DWORD dwFrameSpeed;
} FRAME;
// Obj.cpp
// ...
void CObj::Frame_Move()
{
if (m_tFrame.dwFrameTime + m_tFrame.dwFrameSpeed < GetTickCount())
{
++m_tFrame.iFrameStart;
if (m_tFrame.iFrameStart > m_tFrame.iFrameEnd)
m_tFrame.iFrameStart = 0;
m_tFrame.dwFrameTime = GetTickCount();
}
}
// Player.cpp
// ...
void CPlayer::ChangeState()
{
if (m_ePreState != m_eCurState)
{
switch (m_eCurState)
{
case CPlayer::IDLE:
m_tFrame.iFrameStart = 0;
m_tFrame.iFrameEnd = 3;
m_tFrame.iFrameScene = IDLE;
m_tFrame.dwFrameTime = GetTickCount();
m_tFrame.dwFrameSpeed = 200;
break;
case CPlayer::WALK:
m_tFrame.iFrameStart = 0;
m_tFrame.iFrameEnd = 5;
m_tFrame.iFrameScene = WALK;
m_tFrame.dwFrameTime = GetTickCount();
m_tFrame.dwFrameSpeed = 100;
break;
case CPlayer::ATTACK:
// ...
break;
case CPlayer::HIT:
// ...
break;
case CPlayer::DEAD:
// ...
break;
}
m_ePreState = m_eCurState;
}
}
void CPlayer::Render(HDC _DC)
{
// ...
HDC hMemDC = CBmpMgr::Get_Instance()->Find_Image(m_pFrameKey);
GdiTransparentBlt(_DC
, m_tRect.left + iScrollX, m_tRect.top
, m_tInfo.iCX, m_tInfo.iCY
, hMemDC
, m_tFrame.iFrameStart * 200, m_tFrame.iFrameScene * 200
, 200, 200
, RGB(0, 0, 0));
// ...
}
SceneMgr
// SceneMgr.h
Class CScene;
class CSceneMgr
{
private:
CSceneMgr();
~CSceneMgr();
// 싱글톤
public:
static CSceneMgr* GetInstance();
static void DestroyInstance();
// 가질 수 있는 상태
public:
enum SCENEID { SCENE_LOGO, SCENE_TITLE, SCENE_STAGE_1, SCENE_ENDING, SCENE_END };
void ChangeScene(SCENEID _eScene);
// MainGame에서 호출할 함수
public:
void Update();
void LateUpdate();
void Render(HDC _DC);
CScene* Get_Scene() { return m_pScene; }
private:
void Release();
private:
static CSceneMgr* m_pInstance;
CScene* m_pScene;
SCENEID m_ePreScene; // 현재 상태
SCENEID m_eCurScene; // 변할 상태
};
#define g_SceneMgr CSceneMgr::GetInstance()