๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ Development Study/๐Ÿ’ป Win32API

Tile Map

by eazuooz 2022. 11. 2.

์˜ˆ์ œ :)

https://github.com/eazuooz/WindowAPI/commit/c76d9a833dc8bd2fdaf7feb3fbcac92c9ee2f813

 

TileMap Tool · eazuooz/WindowAPI@c76d9a8

Show file tree Showing 31 changed files with 891 additions and 170 deletions.

github.com

ํƒ€์ผ๋งต์ด๋ž€? ์ผ์ •ํ•œ ํฌ๊ธฐ์™€ ๋ชจ์–‘์„ ๊ฐ€์ง„ ๊ทธ๋ฆผ ์กฐ๊ฐ๋“ค์„ ์˜๋ฏธํ•˜๊ณ , ๊ฒŒ์ž„์—์„œ๋Š” ์ด๋“ค ์กฐ๊ฐ์„ ๋งž์ถ”์–ด์„œ ๊ฒŒ์ž„์˜ ๋ฐฐ๊ฒฝ์„ ์™„์„ฑ์„ ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ ‡๊ฒŒ ์™„์„ฑ์ด ๋œ ๋ฐฐ๊ฒฝ๋“ค์„ ๊ฐ€๋ฆฌ์ผœ์„œ 'ํƒ€์ผ๋งต(TileMap)'์ด๋ผ๊ณ ๋“ค ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

<์ƒ˜ํ”Œ๋กœ ์ œ๊ณต๋˜๋Š” tmw_desert_spacing>

โ–ถ ์œ„ ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด ๊ฒŒ์ž„์—์„œ ํƒ€์ผ์„ ์ด์šฉํ•ด ๋ฐฐ๊ฒฝ๋งต์€ ๋งˆ๋“œ๋Š” ์ด์œ ๋Š” ๊ฒŒ์ž„์˜ ๋ฐฐ๊ฒฝ์ด ์ด์ „ ์ฑ•ํ„ฐ์—์„œ ๊ณต๋ถ€ ํ–ˆ๋˜ ํŒจ๋Ÿด๋ž™์Šค๋…ธ๋“œ์™€ ๊ฐ™์ด ํฌ๊ณ  ๋˜ํ•œ ์žฅ๋ฉด(Scene)์ด ๋งŽ์„ ๊ฒฝ์šฐ์— ๋ฐฐ๊ฒฝ์ด ๋˜๋Š” ๋น„ํŠธ๋งต์„ ๋ชจ๋‘ ๋ฉ”๋ชจ๋ฆฌ์— ์ฝ์–ด๋“ค์—ฌ์•ผ๋งŒ ํ•œ๋‹ค๋ฉด ๋งค์šฐ ํฐ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํƒ€์ผ์„ ์‚ฌ์šฉํ•ด์„œ ๋ฐ˜๋ณตํ•˜๊ฒŒ ๋˜๋ฉด์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ ๋„ ๊ฒŒ์ž„ํ”Œ๋ ˆ์ด์— ํ•„์š”ํ•œ ๋ฐฐ๊ฒฝ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์œ„ ์ด๋ฏธ์ง€๋“ค์„ ์ด์šฉํ•ด์„œ ๊ฐ€๋กœ 20 ์„ธ๋กœ 10์ค„๋กœ ๊ตฌ์„ฑ ๋œ ๋ฐฐ๊ฒฝ์„ ๊ตฌ์„ฑํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ํƒ€์ผ์ด ์ด 200๊ฐœ๋กœ ๊ตฌ์„ฑ์ด ๋œ๊ฒƒ์ธ๊ฐ€์š”? ๋‹ต์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ฐ™์€ ์กฐ๊ฐ๋“ค ์ฆ‰, ํ…์Šค์ฒ˜๋“ค์„ ๊ทธ๋Œ€๋กœ ๊ฐ–๋‹ค ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด์ง€์š”. ๋งต์ด ์ปค์งˆ์ˆ˜๋ก ํƒ€์ผ๋งต์€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์ƒ ์•„์ฃผ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๋ฉ๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์‹œ๊ฐ„์—๋Š” ์ด๋Ÿฐ ํƒ€์ผ๋งต์„ ์ œ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ Tool์„ ์ œ์ž‘ํ•ด๋ณด๋ ค ํ•œ๋‹ค.

์–ด๋–ค ํƒ€์ผ๋“ค์„ ์„ ํƒํ•ด์•ผํ• ์ง€ ์ด๋ฏธ์ง€๋ฅผ ๋„์šธ ์ƒˆ๋กœ์šด ์œˆ๋„์šฐ๋ฅผ ์ƒ์„ฑํ•ด๋ณผ๊ฒƒ์ด๋‹ค.

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // ์ธ์Šคํ„ด์Šค ํ•ธ๋“ค์„ ์ „์—ญ ๋ณ€์ˆ˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
      return FALSE;

   //์œˆ๋„์šฐ ํฌ์ง€์…˜ ๋ฐ ํฌ๊ธฐ ์„ค์ •
   ya::WindowData windowData;
   windowData.hWnd = hWnd;
   windowData.height = 900;
   windowData.width = 1600;

   SetWindowPos(hWnd, nullptr, 0, 0, windowData.width, windowData.height, 0);
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   ya::Application::GetInstance().Initialize(windowData);

   if (ya::SceneManager::GetSecneType() != eSceneType::Tool)
       return TRUE;

   //ATLAS
   hWnd = CreateWindowW(L"AtlasWindow", L"Atlas", WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
   if (!hWnd)
       return FALSE;

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

์œˆ๋„์šฐ๋ฅผ ์ƒ์„ฑํ•ด์ค„๋–„ ์ด์ œ๋Š” 1๊ฐœ์˜ ์œˆ๋„์šฐ๊ฐ€ ์•„๋‹Œ 2๊ฐœ์˜ ์œˆ๋„์šฐ๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  2๋ฒˆ์จฐ ์œˆ๋„์šฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด๋ฏธ์ง€ ํฌ๊ธฐ์— ๋งž์ถ”์–ด ์œˆ๋„์šฐ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•ด์ฃผ๊ณ 

๋งˆ์šฐ์Šค ํด๋ฆญ์‹œ ํ•ด๋‹น ์ด๋ฏธ์ง€์˜ ์ธ๋ฑ์Šค ๋ฒˆํ˜ธ๋ฅผ ๊ฐ€์ ธ์˜ฌ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

LRESULT CALLBACK AtlasWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_CREATE:
	{
		DefWindowProc(hWnd, message, wParam, lParam);

		ya::WindowData atlasWindowData;
		atlasWindowData.hWnd = hWnd;
		atlasWindowData.hdc = GetDC(hWnd);
		atlasWindowData.height = 900;
		atlasWindowData.width = 800;
		ya::Application::GetInstance().SetAtlasWindow(atlasWindowData);

		ya::Scene* pScene = ya::SceneManager::GetPlayScene();
		ya::ToolScene* toolScene = dynamic_cast<ya::ToolScene*>(pScene);

		ya::TilePalatte* atlas = toolScene->GetTilePalatte();
		ya::Image* atlamsImg = atlas->GetImage();

		RECT rect = { 0, 0, atlamsImg->GetWidth(), atlamsImg->GetHeight()};
		AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, false);
		SetWindowPos(atlasWindowData.hWnd
			, nullptr, 1600, 0
			, rect.right - rect.left
			, rect.bottom - rect.top
			, 0);
		ShowWindow(atlasWindowData.hWnd, true);
	}
	break;

	case WM_COMMAND:
	{
		int wmId = LOWORD(wParam);
		// ๋ฉ”๋‰ด ์„ ํƒ์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค:
		switch (wmId)
		{
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
	}
	break;

	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);

		//Rectangle(GetDC(hWnd), 0, 0, 100, 100);

		ya::Scene* pScene = ya::SceneManager::GetPlayScene();
		ya::ToolScene* toolScene = dynamic_cast<ya::ToolScene*>(pScene);

		ya::TilePalatte* atlas = toolScene->GetTilePalatte();
		ya::Image* atlamsImg = atlas->GetImage();

		ya::Vector2 pos(ya::Vector2::Zero);

		TransparentBlt(hdc, (int)pos.x
			, (int)pos.y
			, atlamsImg->GetWidth(), atlamsImg->GetHeight()
			, atlamsImg->GetHdc(), 0, 0, atlamsImg->GetWidth(), atlamsImg->GetHeight(), RGB(255, 0, 255));

		// TODO: ์—ฌ๊ธฐ์— hdc๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ทธ๋ฆฌ๊ธฐ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค...

		EndPaint(hWnd, &ps);
	}
	break;

	case WM_LBUTTONDOWN:
	{
		if (GetFocus())
		{
			POINT mousePos = {};
			GetCursorPos(&mousePos);
			ScreenToClient(hWnd, &mousePos);
			// ๊ฐ€๋กœ 8 ์„ธ๋กœ 6

			int x = mousePos.x / TILE_SIZE;
			int y = mousePos.y / TILE_SIZE;

			int index = (y * 8) + (x % 8);
			ya::Scene* pScene = ya::SceneManager::GetPlayScene();
			ya::ToolScene* toolScene = dynamic_cast<ya::ToolScene*>(pScene);
			toolScene->SetTileIndex(index);
		}
	}
	break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

๊ทธ๋Ÿผ ์šฐ์ธก ์ƒ๋‹จ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์œˆ๋„์šฐ๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋ ๊ฒƒ์ด๋‹ค.

 

์ด์ œ ์ขŒ์ธก ์œˆ๋„์šฐ์— ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํด๋ฆญ๋œ ํƒ€์ผ์„ ์„ค์น˜ํ• ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

๊ทธ์ž‘์—…์€ TilePalatte๋ผ๋Š” ํด๋ž˜์Šค์—์„œ ์ง„ํ–‰ํ•  ๊ฒƒ์ธ๋ฐ ํƒ€์ผ์˜ ์ƒ์„ฑ ๊ด€๋ฆฌ ๋“ฑ ๋ชจ๋“ ๊ฒƒ๋“ค์€ 

๊ด€๋ฆฌํ•ด์ฃผ๋Š” ํด๋ž˜์Šค์ด๋‹ค.

	void TilePalatte::Tick()
	{
		if (KEY_PREESED(KEY_CODE::LBTN))
		{
			if (GetFocus())
			{
				POINT pos = GetTilePos();
				Scene* pScene = SceneManager::GetPlayScene();
				ToolScene* toolScene = dynamic_cast<ToolScene*>(pScene);
				CreateTile(toolScene->GetTileIndex(), Vector2(pos.x, pos.y));
			}
		}
	}

 

์ถ”๊ฐ€์ ์œผ๋กœ ์ƒ์„ฑ๋œ ํƒ€์ผ์„ ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ฌ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋„ ์ถ”๊ฐ€ ํ•ด์ฃผ์—ˆ๋‹ค.

	void TilePalatte::Save()
	{
		// open a file name
		OPENFILENAME ofn = {};

		wchar_t szFilePath[256] = {};

		ZeroMemory(&ofn, sizeof(ofn));
		ofn.lStructSize = sizeof(ofn);
		ofn.hwndOwner = NULL;
		ofn.lpstrFile = szFilePath;
		ofn.lpstrFile[0] = '\0';
		ofn.nMaxFile = 256;
		ofn.lpstrFilter = L"Tile\0*.tile\0";
		ofn.nFilterIndex = 1;
		ofn.lpstrFileTitle = NULL;
		ofn.nMaxFileTitle = 0;
		ofn.lpstrInitialDir = NULL;
		ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

		if (false == GetSaveFileName(&ofn))
			return;

		// ํŒŒ์ผ ์ž…์ถœ๋ ฅ
		FILE* pFile = nullptr;

		// ์“ฐ๊ธฐ ๋ชจ๋“œ๋กœ ์—ด๊ธฐ
		_wfopen_s(&pFile, szFilePath, L"wb");

		if (nullptr == pFile)
			return;

		std::unordered_map<UINT64, Tile*>::iterator iter = mTiles.begin();
		for (; iter != mTiles.end(); ++iter)
		{
			int index = (*iter).second->GetIndex();
			fwrite(&index, sizeof(int), 1, pFile);
			TileID id;
			id.ID = (*iter).first;
			fwrite(&id.ID, sizeof(UINT64), 1, pFile);
		}

		fclose(pFile);
	}

	void TilePalatte::Load()
	{
		OPENFILENAME ofn = {};

		wchar_t szFilePath[256] = {};

		ZeroMemory(&ofn, sizeof(ofn));
		ofn.lStructSize = sizeof(ofn);
		ofn.hwndOwner = NULL;
		ofn.lpstrFile = szFilePath;
		ofn.lpstrFile[0] = '\0';
		ofn.nMaxFile = 256;
		ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
		ofn.nFilterIndex = 1;
		ofn.lpstrFileTitle = NULL;
		ofn.nMaxFileTitle = 0;
		ofn.lpstrInitialDir = NULL;
		ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

		if (false == GetOpenFileName(&ofn))
			return;

		FILE* pFile = nullptr;
		_wfopen_s(&pFile, szFilePath, L"rb");
		
		if (pFile == nullptr)
			return;

		while (true)
		{
			int index = 0;
			TileID id;

			if (fread(&index, sizeof(int), 1, pFile) == NULL)
				break;
			if (fread(&id, sizeof(UINT64), 1, pFile) == NULL)
				break;

			CreateTile(index, Vector2(id.left, id.right));
		}

		fclose(pFile);
	}

'๐Ÿ“ Development Study > ๐Ÿ’ป Win32API' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Gravity  (0) 2022.11.09
UIManager, UIBase  (0) 2022.11.09
Clone Object(๋ณต์‚ฌ ์ƒ์„ฑ์ž)  (0) 2022.10.26
Rigidbody  (0) 2022.10.20
API Math  (0) 2022.10.20

๋Œ“๊ธ€