프로그래밍 공부
작성일
2024. 5. 12. 17:21
작성자
WDmil
728x90

 

필드맵이 이동하는대로 따라 움직이는것과

랜덤한 위치에 Object가 생성되는것,

그리고 이동했던 필드의 위치값에 이미 생성되었던 Object는 그 위치 그대로 다시 Render되게 하였습니다.

 

#pragma once

class Map 
{
	/*
	xz축을 기준으로, 해당 terrain이 player와 해당방향으로 size의 두개 사이즈로 벌어질경우, player의 앞부분에 위치한
	terrain으로 위치를 이동함.
	*/

public:
	Map(Collider* player, Float2 size);
	~Map();

	void Update();
	void Render();
	void GUIRender();
	void SetScail();
private:
	void MakeTerrain();
	void MoveTerrain();

private:
	vector<Terrain*> map;
	Trees* trees;
	Collider* player;
	Float2 defaltsize;
};
 

Map을 정의해주는 객체입니다.

 

map을 Vector형태로 9개 생성하여 관리하며, 따로 다시 생성되거나 줄어드는것이 아닌, Player가 이동하는대로 따라움직입니다.

 

void Map::MakeTerrain()
{
	map.reserve(9);
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++) {
			Terrain* ter = new Terrain();
			ter->GetMaterial()->SetDiffuseMap(L"Textures/Landscape/Floor.png");
			ter->GetMaterial()->SetNormalMap(L"Textures/Landscape/Floor_normal.png");

			defaltsize.x = ter->GetWidth()-1;
			defaltsize.y = ter->GetHeight()-1;
			ter->SetLocalPosition(Vector3((i - 1.5) * defaltsize.x, 0, (j - 1.5) * defaltsize.y));
			ter->UpdateWorld();
			map.push_back(ter);
		}
}

void Map::MoveTerrain()
{
	for (auto& def : map)
	{
		Vector3 pos(def->GetLocalPosition().x + defaltsize.x * 0.5 ,0 ,def->GetLocalPosition().z + defaltsize.y * 0.5);

		if (pos == player->GetLocalPosition()) continue;
		Vector3 nowtoplayer = pos - player->GetLocalPosition();

		float xp = Vector3::Dot(nowtoplayer, Vector3(+1, 0, 0));
		if (xp < 0) xp = 0;
		float xb = Vector3::Dot(nowtoplayer, Vector3(-1, 0, 0));
		if (xb < 0) xb = 0;
		float zp = Vector3::Dot(nowtoplayer, Vector3(0, 0, +1));
		if (zp < 0) zp = 0;
		float zb = Vector3::Dot(nowtoplayer, Vector3(0, 0, -1));
		if (zb < 0) zb = 0;

		Float2 distance = defaltsize;
		distance.x = distance.x * 1.5;
		distance.y = distance.y * 1.5;

		Vector3 movepos = {};
		
		// 우측으로 플레이어가 이동했을 경우,
		if (xp > distance.x)
			movepos.x = -defaltsize.x*3;

		// 좌측으로 플레이어가 이동했을 경우,
		if (xb > distance.x)
			movepos.x = defaltsize.x*3;

		// 위쪽으로 플레이어가 이동했을 경우,
		if (zp > distance.y)
			movepos.z = -defaltsize.y*3;

		// 아래쪽으로 플레이어가 이동했을 경우,
		if (zb > distance.y)
			movepos.z = defaltsize.y*3;

		if(movepos != Vector3(0, 0, 0))
			def->SetLocalPosition(def->GetLocalPosition() + movepos);
	}
}
 

필드를 움직이는 함수와 필드를 생성하는 함수 입니다.

 

생성시, 사이즈의 1.5배만큼 위치값을 이동시키고 생성합니다.

 

(Terrain의 기본생성위치가 좌측하단이기 때문에 보정)

 

움직일 시, 모든 Terrain을 순회하며.

현재 위치가 정중앙일때는 continue

안하면, 위치값이 무작위로 움직이는 버그가 생길 수 있습니다.(float의 비정규화로인한 오류)

 

xp xb zp zb로 하여, x축 z축에 대해 현재 Terrain의 위치값을 판별합니다.

 

그리고, Player의 위치값을 가져온 다음. 해당 Player와 size의 3배만큼 떨어졌을 때.

 

떨어진 방향으로 사이즈만큼 이동시킵니다.

 

그럼으로써 무한맵을 만들어낼 수 있습니다.


#pragma once

class Trees : public SphereCollider
{
	const UINT COUNT = 100;

public:
	Trees();
	~Trees();
	 
	void Update();
	void Render();
	void PostRender();
	void RenderTerraintoTree(pair<float, float> nowpos, Float2 size);

private:
	void ChackRaytoCAM();
	void SetColor();
	void MoveAnimation();
	void MakeTree(pair<float, float> nowpos, Float2 size);
	void RenderTree(pair<float, float> nowpos);

private:
	map<pair<float, float>, vector<Matrix>> treesmap;
	VertexBuffer* instanceBuffer;

	Model* model = nullptr;
};
 

위에 표시할 Model을 생성하는 객체입니다.

 

따로 모델은 못구해 전에 사용했던 사각형을 사용했습니다.

 

void Trees::RenderTerraintoTree(pair<float, float> nowpos, Float2 size)
{
	if (treesmap.count(nowpos) == 0)
		MakeTree(nowpos, size);

	RenderTree(nowpos);
}

void Trees::MakeTree(pair<float, float> nowpos, Float2 size)
{
	FOR(COUNT)
	{
		Float2 minpos(nowpos.first, nowpos.second);
		Float2 maxpos(nowpos.first + size.x, nowpos.second + size.y);

		Vector3 pos(MATH->Random(minpos.x, maxpos.x),0 ,MATH->Random(minpos.y, maxpos.y));

		pair<float, float> result;

		result.first = nowpos.first;
		result.second = nowpos.second;

		Matrix insret = XMMatrixTranslation(pos.x, pos.y, pos.z);
		insret = XMMatrixTranspose(insret);
		treesmap[result].push_back(insret); // 전치행렬화
	}
}

void Trees::RenderTree(pair<float, float> nowpos)
{
	instanceBuffer = new VertexBuffer(treesmap[nowpos].data(), sizeof(Matrix), COUNT);
	instanceBuffer->Set(1);
	model->RenderInstanced(COUNT);
	delete instanceBuffer;
}
 

정의는 위와 같습니다.

 

map에 vector<Matrix>형태의 데이터를 가집니다. COUNT개수만큼(현재는 100개)

 

그리고, 만약, 정의되지 않은 키값에 대한 호출이 있을경우.(이동한적 이 없는 위치로 이동한 Terrain이 존재할경우!)

 

해당되는 map에 대한 데이터를 map에 생성합니다.

 

오브젝트 생성 알고리즘은 간단합니다.

 

최소값과 최대값(각각 Terrain 의 시작지점이 원점부터 size까지임으로 재정의)

로 랜덤하게 flaot값을 받아온뒤.

 

result에 현재 위치값을 키값으로. insert에 수업시간에 했던 Matrix생성 알고리즘을 대입합니다.

 

그렇게 해당되는 map에 위치Matrix를 정의해줍니다.

 

출력은 Buffer를 생성하고 보내주는것과 같습니다.

 

728x90

'작업사항 정리 > DIrectX3D' 카테고리의 다른 글

Animation  (0) 2024.05.13
DirectX3D 작업물 몰아넣은 Git  (0) 2024.05.13
Collision & 회전  (0) 2024.05.12
상점기능 구현  (0) 2024.05.12
간단 PacMan  (0) 2024.05.12