1. LineMesh

이전의 포스트에서 Player를 그렸던 선과 선들의 집합을 mesh로 불러와서 사용할 것이다.

[Windows API & 게임 수학] - 1-8. 리소스 제작 툴 만들기 (Resources, EditScene)

 

1-8. 리소스 제작 툴 만들기 (Resources)

1. EditScene ; 라인을 그리는 Scene SceneManager에 case 문을 추가한다. case SceneType::EditScene: newScene = new EditScene(); break; Enums.h에 아래 코드를 추가한다. enum class SceneType { None, DevScene, GameScene, EditScene, }; Game.

crat.tistory.com

#pragma once
#include "ResourceBase.h"

class LineMesh : public ResourceBase
{
public:
	void Save(wstring path);
	void Load(wstring path);
	void Render(HDC hdc, Pos pos) const;

	vector<pair<POINT, POINT>>& GetLines() { return _lines; }

protected:
	vector<pair<POINT, POINT>> _lines;
	int32 _width = 0;
	int32 _height = 0;
};

이전에에 사용했던 저장, 불러오기 코드를 가져와서 사용한다.

 

(1) 저장

#include "pch.h"
#include "LineMesh.h"
#include <fstream>

void LineMesh::Save(wstring path)
{
	wofstream file;
	file.open(path);

	int32 minX = INT32_MAX;
	int32 maxX = INT32_MIN;
	int32 minY = INT32_MAX;
	int32 maxY = INT32_MIN;

	for (auto& line : _lines)
	{
		POINT from = line.first;

		POINT to = line.second;

		minX = min(min(minX, from.x), to.x);
		maxX = max(max(maxX, from.x), to.x);
		minY = min(min(minY, from.y), to.y);
		maxY = max(max(maxY, from.y), to.y);
	}

	int32 midX = (maxX + minX) / 2;
	int32 midY = (maxY + minY) / 2;


	file << static_cast<int32>(_lines.size()) << endl;

	for (auto& line : _lines)
	{
		POINT from = line.first;
		from.x -= midX;
		from.y -= midY;

		POINT to = line.second;
		to.x -= midX;
		to.y -= midY;

		wstring str = std::format(L"({0},{1})->({2},{3})", from.x, from.y, to.x, to.y);
		file << str << endl;
	}

	file.close();
}

 

(2) 불러오기

void LineMesh::Load(wstring path)
{
	wifstream file;
	file.open(path);

	// 라인의 갯수
	int32 count;
	file >> count;

	_lines.clear();

	for (int32 i = 0; i < count; i++)
	{
		// pt1과 pt2에 정보 저장하기
		POINT pt1 = {};
		POINT pt2 = {};

		wstring str;
		file >> str;
		// %d : 정수, %s : 문자
		::swscanf_s(str.c_str(), L"(%d,%d)->(%d,%d)", &pt1.x, &pt1.y, &pt2.x, &pt2.y);

		_lines.push_back(make_pair(pt1, pt2));
	}
	file.close();

	// width, height
	int32 minX = INT32_MAX;
	int32 maxX = INT32_MIN;
	int32 minY = INT32_MAX;
	int32 maxY = INT32_MIN;

	for (auto& line : _lines)
	{
		minX = min(minX, min(line.first.x, line.second.x));
		maxX = max(maxX, max(line.first.x, line.second.x));
		minY = min(minY, min(line.first.y, line.second.y));
		maxY = max(maxY, max(line.first.y, line.second.y));
	}

	_width = maxX - minX;
	_height = maxY - minY;
}

 

2. ResourceManager

EditScene 또는 기타 툴로 만든 리소스들을 관리한다.

 

(1) ResourceManager.h

#pragma once

class ResourceBase;
class LineMesh;

class ResourceManager
{
	DECLARE_SINGLE(ResourceManager);

	~ResourceManager();

public:
	void Init();
	void Clear();

	const LineMesh* GetLineMesh(wstring key);

private:
	unordered_map<wstring, LineMesh*> _lineMeshes;
};

GetLineMesh 함수를 통해 어떤 key 값을 입력하면 mesh를 리턴하도록 할 것이다.

 

(2) ResourceManager.cpp

#include "pch.h"
#include "ResourceManager.h"
#include "LineMesh.h"

ResourceManager::~ResourceManager()
{
	Clear();
}

void ResourceManager::Init()
{
	{
		LineMesh* mesh = new LineMesh();
		mesh->Load(L"Player.txt");
		// key를 Player로 지정
		_lineMeshes[L"Player"] = mesh;
	}
}

void ResourceManager::Clear()
{
	for (auto mesh : _lineMeshes)
		SAFE_DELETE(mesh.second);

	_lineMeshes.clear();
}

const LineMesh* ResourceManager::GetLineMesh(wstring key)
{
	auto findIt = _lineMeshes.find(key);
	if (findIt == _lineMeshes.end())
		return nullptr;

	return findIt->second;
}

이전에 EditScene에서 직접 만들었던 player의 비행기를 Player.txt로 저장했었는데, 해당 정보를 mesh에 불러오기 하여 저장한다.

이 때 키는 Player가 되고, 값은 mesh가 된다.

 

(3) 초기화 하기

Game.cpp의 Init 함수에서 ResourceManager를 초기화하는 코드를 추가한다.

	GET_SINGLE(ResourceManager)->Init();

또한 Game의 소멸자에서 Clear를 하도록 추가한다.

Game::~Game()
{
	GET_SINGLE(SceneManager)->Clear();
	GET_SINGLE(ResourceManager)->Clear();
}

 

3. LineMesh의 Render 함수

EditScene의 Render 함수를 가져와 사용한다.

void LineMesh::Render(HDC hdc, Pos pos) const
{
	for (auto& line : _lines)
	{
		POINT pt1 = line.first;
		POINT pt2 = line.second;

		Pos pos1;
		pos1.x = pos.x + (float)pt1.x;
		pos1.y = pos.y + (float)pt1.y;

		Pos pos2;
		pos2.x = pos.x + (float)pt2.x;
		pos2.y = pos.y + (float)pt2.y;

		Utils::DrawLine(hdc, pos1, pos2);
	}
}

기존에는 상대 좌표에 대하여 그려지고 있었으므로, 코드를 수정한다.