티스토리 뷰
Project Note #001
Mole Catch
Window API
를 활용해 만든 게임, Mole Catch
에 대해 알아봅니다.- 참고
※ https://youtu.be/quCLlsKS_uU (플레이 영상)
※ https://github.com/BaeMinCheon/mole-catch (Github)
Window API
를 활용해 만든 게임, Mole Catch
에 대해 알아봅니다.※ https://youtu.be/quCLlsKS_uU (플레이 영상)
※ https://github.com/BaeMinCheon/mole-catch (Github)
환경
- Visual Studio 2015 Community
- Windows 10 Home
- Window API (C/C++)
소개
- 주어진 생명력이 0으로 떨어질 때까지, 두더지를 최대한 많이 잡아 고득점을 획득하는 것이 목표인 게임입니다.
※ 두더지를 잡을 때마다 게임점수 1을 획득하며, 놓칠 때마다 생명력 1을 잃습니다. 점수가 높아질수록 두더지들이 빠르게 사라집니다. - 학술동아리에서
Window API
를 공부하고, 이를 적용해보자 만든 게임입니다.
※ https://goo.gl/cNTKwY (많은 부분을 해당 링크에서 참고했습니다)
※ 두더지를 잡을 때마다 게임점수 1을 획득하며, 놓칠 때마다 생명력 1을 잃습니다. 점수가 높아질수록 두더지들이 빠르게 사라집니다.
Window API
를 공부하고, 이를 적용해보자 만든 게임입니다.※ https://goo.gl/cNTKwY (많은 부분을 해당 링크에서 참고했습니다)
분석
화면 분리
/
① 각 화면들의 이름을 열거형으로 구분하고, 클래스로 구현합니다.
ex)
enum Sequence { Title = 0, Start = 1, Help = 2, Gameover = 3 };
namespace Scene { class Title { ... } }
/
② 기본적으로 4가지의 함수를 가지고, 해당 화면에 필요한 객체들을 별도로 포함합니다.
Initialize()
: 해당 화면의 객체들을 동적할당하는 기능
Release()
: 해당 화면에 동적할당되었던 객체들을 해제하는 기능
Update()
: 사용자의 입력을 받는 기능
Draw()
: 화면을 출력하는 기능
ex)
namespace Scene { class Title { public: static Button* B1; static Button* B2; static Button* B3; static VOID Initialize(HWND hWnd); static VOID Release(VOID); static VOID Update(VOID); static VOID Draw(HDC hDC); }; }
/
③ 각 화면들은 사전에 Initialize()
를 통해 미리 생성되고, 초기화가 필요한 경우 Release()
와 Initialize()
를 순서대로 실행합니다.
Scene::Start::Release(); Scene::Start::Initialize(hWnd);
/
④ 현재 화면을 열거형으로 저장하고, 이를 통해 현재 화면에서만 입력과 출력을 수행합니다.
ex)
Sequence nSeq = Sequence::Title;
switch(nSeq) { case Sequence::Title: ... break; ... }
화면 출력
/
① Window API
는 메시지기반으로 동작하지만, 게임은 프레임기반으로 동작해야합니다. 따라서, 메시지가 없거나 메시지가 WM_PAINT
인 경우에 출력을 하는 방식을 채용합니다.
while(true) { if(PeekMessage(pMsg, nullptr, NULL, NULL, PM_REMOVE) && pMsg->message != WM_PAINT) { ... } else { hResult = OnPaint(hWnd); ... } }
/
② 빠른 속도를 내기 위해 BYTE
배열로 화면을 편집합니다.
BYTE* pMem = reinterpret_cast<BYTE*>(malloc(800 * 600 * 4));
memset()
또는 memcpy()
를 통해 pMem
를 편집합니다.
/
③ 화면 내 객체는 각자의 Draw()
함수를 사용합니다.
ex)
B1->Draw(hDC); B2->Draw(hDC); B3->Draw(hDC);
입력 처리
/
① 키보드 입력 처리 : WndProc
내에서 WM_KEYDOWN
메시지로 처리합니다.
case WM_KEYDOWN: if(p_wParam == VK_ESCAPE) { ... } ... break;
/
② 마우스 입력 처리 : 객체마다의 Update()
함수에서 처리합니다.
해당 윈도우에 대한 클릭인지 검사 if((GetKeyState(VK_LBUTTON) & 0x8000) && (GetActiveWindow() == hWnd))
새로운 입력인지 검사 if(!bClick && !bPrevClick)
맞다면 새로운 입력에 대한 처리 진행, 아니라면 연이은 입력에 대한 처리 진행
해당 윈도우에 대한 클릭이 없을 경우 if((GetKeyState()...)) { ... } else { [HERE] }
이전에 클릭이 있었는지 검사 if(bClick) { ... }
맞다면 클릭이 끝났을 때에 대한 처리 진행, 아니라면 bClick = FALSE; bPrevClick = FALSE;
실행 후 마침
화면 분리
/
① 각 화면들의 이름을 열거형으로 구분하고, 클래스로 구현합니다.
ex)enum Sequence { Title = 0, Start = 1, Help = 2, Gameover = 3 };
namespace Scene { class Title { ... } }
/
② 기본적으로 4가지의 함수를 가지고, 해당 화면에 필요한 객체들을 별도로 포함합니다.Initialize()
: 해당 화면의 객체들을 동적할당하는 기능Release()
: 해당 화면에 동적할당되었던 객체들을 해제하는 기능Update()
: 사용자의 입력을 받는 기능Draw()
: 화면을 출력하는 기능
ex)namespace Scene { class Title { public: static Button* B1; static Button* B2; static Button* B3; static VOID Initialize(HWND hWnd); static VOID Release(VOID); static VOID Update(VOID); static VOID Draw(HDC hDC); }; }
/
③ 각 화면들은 사전에 Initialize()
를 통해 미리 생성되고, 초기화가 필요한 경우 Release()
와 Initialize()
를 순서대로 실행합니다.Scene::Start::Release(); Scene::Start::Initialize(hWnd);
/
④ 현재 화면을 열거형으로 저장하고, 이를 통해 현재 화면에서만 입력과 출력을 수행합니다.
ex)Sequence nSeq = Sequence::Title;
switch(nSeq) { case Sequence::Title: ... break; ... }
화면 출력
/
① Window API
는 메시지기반으로 동작하지만, 게임은 프레임기반으로 동작해야합니다. 따라서, 메시지가 없거나 메시지가 WM_PAINT
인 경우에 출력을 하는 방식을 채용합니다.while(true) { if(PeekMessage(pMsg, nullptr, NULL, NULL, PM_REMOVE) && pMsg->message != WM_PAINT) { ... } else { hResult = OnPaint(hWnd); ... } }
/
② 빠른 속도를 내기 위해 BYTE
배열로 화면을 편집합니다.BYTE* pMem = reinterpret_cast<BYTE*>(malloc(800 * 600 * 4));
memset()
또는 memcpy()
를 통해 pMem
를 편집합니다.
/
③ 화면 내 객체는 각자의 Draw()
함수를 사용합니다.
ex)B1->Draw(hDC); B2->Draw(hDC); B3->Draw(hDC);
입력 처리
/
① 키보드 입력 처리 : WndProc
내에서 WM_KEYDOWN
메시지로 처리합니다.case WM_KEYDOWN: if(p_wParam == VK_ESCAPE) { ... } ... break;
/
② 마우스 입력 처리 : 객체마다의 Update()
함수에서 처리합니다.
해당 윈도우에 대한 클릭인지 검사 if((GetKeyState(VK_LBUTTON) & 0x8000) && (GetActiveWindow() == hWnd))
새로운 입력인지 검사 if(!bClick && !bPrevClick)
맞다면 새로운 입력에 대한 처리 진행, 아니라면 연이은 입력에 대한 처리 진행
해당 윈도우에 대한 클릭이 없을 경우 if((GetKeyState()...)) { ... } else { [HERE] }
이전에 클릭이 있었는지 검사 if(bClick) { ... }
맞다면 클릭이 끝났을 때에 대한 처리 진행, 아니라면 bClick = FALSE; bPrevClick = FALSE;
실행 후 마침
이상으로 노트를 마칩니다.
'Project' 카테고리의 다른 글
#006 : Unlight Copycat [DAY #05] (0) | 2018.02.26 |
---|---|
#005 : Unlight Copycat [DAY #04] (0) | 2018.02.25 |
#004 : Unlight Copycat [DAY #03] (0) | 2018.02.25 |
#003 : Unlight Copycat [DAY #02] (0) | 2018.02.23 |
#002 : Unlight Copycat [DAY #01] (0) | 2018.02.22 |
- Total
- Today
- Yesterday
- unity
- vscode
- lib
- tensorflow
- Hashtable
- windows
- Docker
- WindowAPI
- Game
- Python
- DirectX
- visualstudio
- dll
- pclaf
- CUDA
- PopeTV
- shader
- CAFFE
- JIT
- unreal
- Slack
- git
- ATOM
- visual-studio
- csharp
- C/C++
- cuDNN
- NOX
- Anaconda
- A.I.
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |