*** 공부 방법 ***
1. 코딩을 해야 하는 부분은 첫 부분에 변수나 함수, 메소드에 대한 선언이 코드블럭으로 표시되어 있다. //ex) MakeFunction(); 2. 코드블럭 하단에는 해당 선언에 대한 구현 로직이 작성되어 있다. 처
hyrule.tistory.com
- 타일맵을
쓰는 이유는 편의성에 있다.
- 맵을 일일히 그려낼 필요 없이, 타일 배치에 따라서 맵을 만들 수 있게 되기 때문이다.
- 아예 맵을 마우스를 이용해 찍어낼 수 있다면, 더욱더 편할 것이다.
- 다이얼로그 창을 하나 만든다. 필터에 우클릭 - 추가 - 리소스 - 다이얼로그를 해주면 된다.
- 그러면 이런 창이 뜬다.
- 이후 이 창에서 ALT + ENTER를 입력 시 '속성' 창을 띄울 수 있다.
이 창에서 값을 계속 바꿔주어야 하므로 드래그해서 솔루션 탐색기와 같이 띄워놓는다
- 속성 창에서 '캡션'을 TileMap으로 바꿔 준다.
-- '캡션'은 다이얼로그 내 특정 오브젝트의 이름 역할을 한다.
- 이후 창에 각종 오브젝트를 배치하는 것은 '도구 상자'에서 할 수 있다.
위 이미지를 보면 우측 위에 도구상자 메뉴가 있는 것을 볼수 있다.
저걸 클릭해서 열거나, 혹시 없다면 메뉴 - 보기 - 도구 상자를 해주면 된다.
- Static Text: 수정 불가능한 정보 표시용 텍스트를 생성한다.
-- 속성 창에서 내용을 수정할 수 있다. 내용은 '캡션'을 변경하면 된다.
- Edit Control: 입력란을 만든다.
-- 속성 창에서 ID를 변경할 수 있다. ID에 해당 입력란이 어떤 정보를 입력받는지 작성해놓는 것이 좋다.
- 이렇게, CountX를 입력받을 수 있는 Static Text와 Edit Control 란을 만들어 놓자.
- 파일 탐색기와 비슷하게, Ctrl을 누른 채로 오브젝트들을 클릭하면 다중 선택이 가능하다.
-- 이 상태로 그대로 드래그하면 선택한 오브젝트들이 복제가 된다.
-- 복제한 후 CountY 입력란을 만들어준다.
- Edit Control의 속성 - 숫자 란을 true로 바꿔 주면 숫자만 입력받을 수 있다.
-- Count 란이므로 숫자만 받도록 해준다.
- 저 두 입력란을 그대로 아래로 복사해서 SizeX와 SizeY로 받는다.
- 이제 저 값대로 생성해주는 버튼을 하나 배치한다.
-- 도구 상자의 Button을 배치하면 된다. 캡션을 '생성'으로 바꿔준다.
- 일단은 여기까지 만들어놓고, 실제로 타일맵을 Count와 Size 대로 생성해주는 기능을 만들어보자.
class CGameManager
- 우선 에딧 모드를 확인하기 위한 변수
{ bool m_EditMode } 를 만들어준다.
< Set / Get > 메소드도 만들어준다.
class CSceneEdit: public CScene
[ 헤더 파일 전문 ]
#pragma once
#include "Scene.h"
class CSceneEdit :
public CScene
{
friend class CSceneManager;
protected:
CSceneEdit();
virtual ~CSceneEdit();
public:
bool Init();
private:
class CEditDlg* m_TileMapDlg;
CSharedPtr<class CTileMap> m_TileMap;
public:
void CreateTileMap(int CountX, int CountY, int SizeX, int SizeY);
void SetTileTexture(class CTexture* Texture);
public:
void MoveLeft();
void MoveRight();
void MoveUp();
void MoveDown();
void OpenTileMapEditor();
};
- 에디트 모드용 씬을 하나 만들어주고,
프로그램을 실행시키면 가장 처음으로 나오는 씬에 버튼을 추가하고 누르면 이 씬으로 들어갈 수 있도록 작업해준다.
- 이 씬에서 편집 작업을 편하게 하기 위해 비주얼 스튜디오의 '다이얼로그' 기능을 사용해준다.
-- 일종의 GUI '창'을 새로 띄우는 것 -> HWND를 새로 받아서 생성하는 것
< 생성자 / 소멸자 >
- 이 씬으로 들어올 때 CGameManager의 m_EditMode 변수를 true로 변경해 주고, 씬에서 나갈 때 다시 false로 되돌려 준다.
< void OpenTileMapEditor() >
- 이 창에서, 다이얼로그 창이 생성되도록 해주어야 한다.
-- Input 클래스를 통해 원하는 단축키를 지정해서 이 함수를 콜백함수로 호출되게 해준다.
-- 생성된 클래스에서도 현재 씬 클래스로 정보를 전달할 수 있도록 m_Scene에 주소를 등록해 주어야 한다.
{ class CEditDlg* m_TileMapDlg }
- 다이얼로그 클래스 포인터. 생성자에서 nullptr로 초기화해주고 소멸자에서 SAFE_DELETE 매크로를 통해 제거해준다.
- 단축키를 누르면 호출되는 콜백함수에서 이 클래스를 동적 할당하고, m_Scene 변수에 자신을 등록한 뒤 초기화 메소드를 호출까지 해준다.
class CSceneEditDlg
[ 헤더 파일 전문 ]
#pragma once
#include "../GameInfo.h"
class CSceneEditDlg
{
friend class CEditScene;
private:
CSceneEditDlg();
~CSceneEditDlg();
private:
class CEditScene* m_Scene;
HWND m_hDlg;
HWND m_hTextureListBox;
int m_SelectTextureIndex;
TCHAR m_SelectTextureName[128];
CSharedPtr<class CTexture> m_SelectTexture;
public:
bool Init();
void CreateTileMap();
void LoadTexture();
void SelectTexture();
private:
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};
- 다이얼로그 창을 처리해 줄 클래스.
- CEditScene에서 자유롭게 접근할 수 있도록 friend 처리를 해준다.
{ CSceneEdit* m_Scene }
- 에딧씬의 주소를 들고 있는다. 계속 서로 정보를 교환받아야 하기 때문이다.
{ HWND m_hDLG }: 다이얼로그의 윈도우 핸들 변수
< static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) >
- 다이얼로그도 마찬가지로 창 형태이므로 윈도우 프로시저 콜백함수가 필요하다.
< Init() >
- 다이얼로그는 크게 Modal과 Modeless의 두 가지 유형이 있다.
-- Modal: 부모 윈도우를 멈추고 다이얼로그만 동작함
-- Modeless: 부모 윈도우와 다이얼로그 모두 동작함.
- m_hDlg = CreateDialog(인자 1, 인자 2, 인자 3, 인자 4) > : Init()에서 호출.
-- 모달리스 유형의 다이얼로그를 생성한다.
-- 인자 1: HINSTANCE -> 현재 윈도우 창의 HINSTANCE를 넣어주면 된다.
-- 인자 2: 여기엔 창의 '이름'을 넣어줘야 한다.
--- 다이얼로그를 만든 뒤 빌드를 해보면 resource.h 헤더에 이렇게 우리가 만든 오브젝트 번호가 정의되어 있는 것을 확인할 수 있다.
--- 우리가 만든 다이얼로그의 번호인 IDD_DIALOG_EDIT를, MAKEINTRESOURCE()라는 함수 안에 인자로 넣어서 전달해주면, 알아서 이름을 만들어서 인자로 전달해준다.
-- 인자 3: 부모 윈도우의 핸들 -> 메인 윈도우의 핸들을 전달하면 된다.
-- 인자 4: 윈도우 프로시저 함수의 주소.
-- ShowWindow(m_hDLG, SW_SHOW)
--- 창을 띄워준다.
-- SetDlgItemInt(m_hDlg, IDC_EDIT_COUNTX, 40, TRUE)
--- 다이얼로그 특정 오브젝트의 값을 정수로 지정해준다.
--- 예를 들어 위의 인자로 설정하게 되면 COUNTX의 입력란에 40을 기본값으로 입력해준다는 의미이다.
--- 4번째 인자는 signed/unsigned 여부이다.
< WndProc() >
- 다이얼로그와의 상호작용(버튼클릭, x버튼 클릭 등) 은 이쪽으로 메시지가 들어온다.
switch (message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
- 이런 방식으로 처리해주면 된다.
-- X버튼 클릭: WM_CLOSE 메시지 전달
DestroyWindow(hWnd) -> WM_DESTROY 메시지 전달
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON_CREATE_TILEMAP:
-- 직접 만든 버튼 클릭: WM_COMMAND 메시지가 들어오고, wParam으로 어떤 오브젝트인지가 전달.
---CF) WPARAM wParam, LPARAM lParam
---- WM_COMMAND 메시지가 전달되었을 때,
LPARAM에는 메시지를 발생시킨 윈도우 핸들이 전달된다.
---- WPARAM은 HIWORD와 LOWORD 두 파트로 나누어 정보를 전달한다.
HIWORD(wParam)에는 통지 메시지에 대한 정보가 들어있고,
LOWORD(lParam)에는 메시지를 발생시킨 객체의 ID(아까 속성 창에서 변경하고, resource.h에 매크로 작성되어있던 그 ID)가 들어 있다.
-- 그래서 위와 같이 switch문을 통해 정보를 받을 수 있게 된다.
-- 그런데, 문제가 하나 존재한다. WndProc() 함수는 정적 함수이기 때문에, 멤버 함수의 주소를 얻어올 수가 없다.
-> 클래스 주소를 받아와서 멤버 함수를 호출할 수가 없는 것이다.
--- 그러므로, 전역 또는 정적 포인터 변수로 CEditDlg의 주소를 받아와서 처리해주어야 한다.
{ (전역 변수) CEditDlg* g_Dlg = nullptr; }
- 이렇게 선언해 주고, CEditDlg의 생성자에서 자신의 주소를 여기에 등록하고, 소멸자에서 이 주소를 nullptr로 바꿔 준다.
< CreateTileMap() >
- case IDC_BUTTON_CREATE_TILEMAP에서 호출될 함수.
- 버튼을 누른것이 확인되면, 다이얼로그에 입력된 값을 이쪽으로 받아와야 한다.
- GetDlgItemInt() 함수를 이용한다.
BOOL Transfer = FALSE;
int CountX = GetDlgItemInt(m_hDlg, IDC_EDIT_COUNTX, &Transfer, TRUE);
int CountY = GetDlgItemInt(m_hDlg, IDC_EDIT_COUNTY, &Transfer, TRUE);
int SizeX = GetDlgItemInt(m_hDlg, IDC_EDIT_SIZEX, &Transfer, TRUE);
int SizeY = GetDlgItemInt(m_hDlg, IDC_EDIT_SIZEY, &Transfer, TRUE);
- 위의 BOOL 변수의 주소를 전달하면, 해당 변수에 전송 성공 여부를 반환해준다. 걱정된다면 이 변수를 통해 매번 확인해주면 된다.
- 이런 방식으로 CountX, CountY, SizeX, SizeY 모두 받아온다.
- 변수를 받아왔으면, CEditScene을 통해 씬으로 접근해서
CreateTileMap() 메소드를 호출해 타일맵을 실제로 생성 해준다.
class CEditScene
{ CSharedPtr<class CTileMap> m_TileMap }
< void CreateTileMap(int CountX, int CountY, int SizeX, int SizeY) >
- 이 메소드를 통해 새 타일맵을 생성해준다. CGameObect이므로 CreateObject<>()로 생성해 줄 수 있다.
- 일단 중간 작동 여부를 테스트하기 위해 여기까지만 작성한 뒤 테스트를 해보았다.
(아직 작성하지 않은 LoadTexture, SelectTexture 메소드들은 사용하지 않고, 코드에 직접 타일 텍스처를 추가한 뒤 확인하였음)
'WIN32API FrameWork > 한단계씩 직접 구현' 카테고리의 다른 글
71. 타일맵 에디터2: 타일에 텍스처 지정 (0) | 2022.06.13 |
---|---|
70. Font 관련 수정 (0) | 2022.06.13 |
68. 타일 맵 (0) | 2022.06.10 |
67. 화면의 확대 (0) | 2022.06.10 |
66. 오브젝트 컬링 (0) | 2022.06.09 |