2025. 4. 8. 23:35ㆍ원티드_언리얼RPG 2기/WinApi
타일맵 툴 만들기
타일맵 에디터에서 위치와 인덱스 계산은 크게 두 부분으로 나눌 수 있다
- 샘플 타일 영역에서의 선택 - 사용자가 배치할 타일을 고르는 부분
- 메인 맵 영역에서의 배치 - 선택한 타일을 실제 맵에 배치하는 부분
각 문제를 더 작은 단계로 분해해보자
샘플 타일 영역 처리 단계
- 영역 확인: 마우스가 샘플 타일 영역 안에 있는지 확인
- 상대 좌표 계산: 샘플 타일 영역 내에서의 마우스 위치 계산
- 타일 인덱스 계산: 상대 좌표를 타일 크기로 나누어 타일 인덱스 계산
메인 맵 영역 처리 단계
- 영역 확인: 마우스가 메인 맵 영역 안에 있는지 확인
- 타일 위치 계산: 메인 맵 내에서 마우스가 위치한 타일 좌표 계산
- 타일 정보 업데이트: 계산된 위치에 선택된 타일 정보 적용
윈도우좌표계는 좌측상단기준으로 (0,0)이다. 따라서 마우스 위치로 상대좌표를 계산하려면
상대영역 사각형의 left 를뺀값이 x좌표 , 사각형의 top을 뺀 값이 y좌표이다.
if (PtInRect(&rcSampleTile, g_ptMouse)) // 샘플 타일 영역 확인
{
if (KeyManager::GetInstance()->IsOnceKeyDown(VK_LBUTTON))
{
int posX = g_ptMouse.x - rcSampleTile.left; // 상대 X 좌표 계산
int posY = g_ptMouse.y - rcSampleTile.top; // 상대 Y 좌표 계산
selectedTile.x = posX / TILE_SIZE; // X 인덱스 계산
selectedTile.y = posY / TILE_SIZE; // Y 인덱스 계산
}
}
else if (PtInRect(&rcMain, g_ptMouse)) // 메인 맵 영역 확인
{
if (KeyManager::GetInstance()->IsStayKeyDown(VK_LBUTTON))
{
int posX = g_ptMouse.x; // 절대 X 좌표
int posY = g_ptMouse.y; // 절대 Y 좌표
int tileX = posX / TILE_SIZE; // 타일 X 위치 계산
int tileY = posY / TILE_SIZE; // 타일 Y 위치 계산
tileInfo[tileY * TILE_X + tileX].frameX = selectedTile.x; // 선택된 타일의 X 인덱스 적용
tileInfo[tileY * TILE_X + tileX].frameY = selectedTile.y; // 선택된 타일의 Y 인덱스 적용
}
}
마우스 위치가 샘플타일 영역에 있고 왼쪽버튼을 누르면 if문이 실행, 메인영역에있고 마우스 왼쪽버튼이 눌려있는 상태면 else if문이 실행된다.
타일맵 파일 저장,로드기능 만들기
Windows 환경에서의 파일 입출력은 크게 두 가지 방식으로 할 수 있다:
- C++ 스트림(fstream) 사용
- Windows API 사용
2주차 강의에 C++에서 제공하는 라이브러리 <fstream>, <ostream> 에서 파일입출력을 관리하는 실습을 했다.
이번에는 WinApi에서 제공하는 파일입출력함수를 써보려고 한다.
Windows API 파일 입출력 기본 단계:
- 파일 열기/생성: CreateFile() 함수 사용
- 데이터 읽기/쓰기: ReadFile()/WriteFile() 함수 사용
- 파일 닫기: CloseHandle() 함수 사용
CreateFile함수의 원형을 보자
HANDLE CreateFile(
LPCTSTR lpFileName, // 파일 이름
DWORD dwDesiredAccess, // 접근 모드 (읽기/쓰기)
DWORD dwShareMode, // 공유 모드
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 보안 속성
DWORD dwCreationDisposition, // 생성 방식
DWORD dwFlagsAndAttributes, // 파일 속성
HANDLE hTemplateFile // 템플릿 파일 핸들
);
CreateFile은 파일 Create, Open, Write 등의 동작을 할 때 호출되는 함수로 리턴형이 HANDLE이다.
주요 매개변수:
lpFileName: 파일 경로 및 이름
dwDesiredAccess:
- GENERIC_READ: 읽기 전용
- GENERIC_WRITE: 쓰기 전용
dwCreationDisposition:
- CREATE_ALWAYS: 항상 새 파일 생성, 기존 파일 덮어쓰기
- OPEN_EXISTING: 기존 파일 열기
Write / Read file함수의 원형
BOOL WriteFile(
HANDLE hFile, // 파일 핸들
LPCVOID lpBuffer, // 쓸 데이터 버퍼
DWORD nNumberOfBytesToWrite, // 쓸 바이트 수
LPDWORD lpNumberOfBytesWritten, // 실제 쓴 바이트 수
LPOVERLAPPED lpOverlapped // 비동기 작업용 (보통 NULL)
);
BOOL ReadFile(
HANDLE hFile, // 파일 핸들
LPVOID lpBuffer, // 읽어올 버퍼
DWORD nNumberOfBytesToRead, // 읽을 바이트 수
LPDWORD lpNumberOfBytesRead, // 실제 읽은 바이트 수
LPOVERLAPPED lpOverlapped // 비동기 작업용 (보통 NULL)
);
파일을 저장하는 Save()함수
void TilemapTool::Save()
{
// 파일 생성
HANDLE hFile = CreateFile(
L"TileMapData.dat", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(g_hWnd, TEXT("파일 생성 실패"), TEXT("경고"), MB_OK);
return;
}
DWORD dwByte = 0;
// 데이터 쓰기
WriteFile(hFile, tileInfo, sizeof(tileInfo), &dwByte, NULL);
// 파일 닫기
CloseHandle(hFile);
}
TileMapData.dat 라는 이름으로 기존파일을 덮어쓰는 쓰기전용 파일을 만들었다.
저장된 파일을 불러오는 Load()함수
void TilemapTool::Load()
{
// 파일 열기
HANDLE hFile = CreateFile(
L"TileMapData.dat", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(g_hWnd, TEXT("파일 열기 실패"), TEXT("경고"), MB_OK);
return;
}
DWORD dwByte = 0;
// 데이터 읽기
ReadFile(hFile, tileInfo, sizeof(tileInfo), &dwByte, NULL);
// 파일 닫기
CloseHandle(hFile);
}
TileMapData.dat 라는 이름의 기존파일을 여는 읽기전용 파일을 만들었다.
궁금증: Load함수는 이미 저장된 파일을 읽어오는데 CreateFile()을 해야할까?
정답: Windows API에서 파일을 다룰 때는 모든 파일 작업(읽기/쓰기 모두)이 파일을 먼저 "열어야" 가능, 그리고 파일을 여는 함수가 바로 CreateFile()이다.
CreateFile()은 이름과 다르게 새 파일 생성/ 기존 파일 열기/ 디바이스 열기(파일 뿐아니라 장치도 열수있다) 다양한 기능을 할 수 있다. 즉 파일을 생성한다기보다 파일 핸들을 생성하는 함수라고 생각하는게 좋다. 파일을 읽으려면 먼저 파일에 접근할 수 있는 "핸들(손잡이)"이 필요한데, 그 핸들을 얻는 과정이 CreateFile()인 것이다.
'원티드_언리얼RPG 2기 > WinApi' 카테고리의 다른 글
맵 에디터 만들기 (0) | 2025.04.29 |
---|---|
씬 매니저로 관리하기 (0) | 2025.04.09 |
탱크 만들기 (0) | 2025.03.10 |
0305 화면에 도형 그리기/ 마우스,키보드로 입출력받아 움직이기 (0) | 2025.03.06 |
0304 WinApi로 자동차 만들기 (0) | 2025.03.04 |