프로그래밍 공부
작성일
2023. 10. 30. 16:09
작성자
WDmil
728x90

우선 원래 만들었던 Scene이 아닌 새로운 Scene을 사용하여 새 게임을 제작한다.

#pragma once

class ShootingScene : public Scene
{
public:
	ShootingScene();
	~ShootingScene();


	// Scene을(를) 통해 상속됨
	void Update() override;
	void PreRender() override;
	void Render() override;
	void PostRender() override;
	void GUIRender() override;
	
private:
	Terrain* terrain;
	ShootingPlayer* player;
};

이미 만들었던 Scene을 상속받고 가상함수 구현을 하면 알아서 구현해준다.

 

Terrain은 전에 만들어놓았던 필드값이고,

 

ShootingPlayer는 Collider를 사용한 사용자 객체이다.

#include "Framework.h"
#include "ShootingScene.h"

ShootingScene::ShootingScene()
{
	terrain = new Terrain();
	player = new ShootingPlayer();
	player->SetTerrain(terrain);
}

ShootingScene::~ShootingScene()
{
	delete terrain;
	delete player;
}

void ShootingScene::Update()
{
	player ->Update();
}

void ShootingScene::PreRender()
{

}

void ShootingScene::Render()
{
	player->Render();
	terrain->Render();
}

void ShootingScene::PostRender()
{
	player->PostRender();
}

void ShootingScene::GUIRender()
{
}

ShootingPlayer

#pragma once

class ShootingPlayer : public SphereCollider
{
public:
	ShootingPlayer();
	~ShootingPlayer();

	void Update();
	void PostRender();

	void SetTerrain(Terrain* terrain) { this->terrain = terrain; }

private:
	void Move();
private:
	float moveSpeed = 5;
	float rotSpeed = 5;

	Terrain* terrain;

	Quad* cursor;
};

ShootingPlayer는 SphereCollider를 상속받아 이루어진다.

 

SphereCollider는 구체형 충돌객체이다.

 

SetTerrain을 사용하여 필드를 참조받아 사용할 수 있게 한다.

 

위 객체는 필드 위를 이동할 때 높이값을 참조받아야 하기 때문.

 

그 외에는

이동할때 필요한 Move()함수,

 

이동속도, 회전속도, 받아올 필드의 포인터값.이다.


#include "Framework.h"

ShootingPlayer::ShootingPlayer()
{
	cursor = new Quad(L"Textures/UI/cursor.png");
	cursor->SetLocalPosition({ CENTER_X, CENTER_Y, 0.0f });
	cursor->UpdateWorld();
}

ShootingPlayer::~ShootingPlayer()
{
	delete cursor;
}

void ShootingPlayer::Update()
{
	Move();
	UpdateWorld();
}

void ShootingPlayer::PostRender()
{
	cursor->Render();
}

void ShootingPlayer::Move()
{
	if (KEY->Press('W'))
	{
		Vector3 forward = GetForward();
		forward.y = 0;
		Translate(forward.GetNormalized() * moveSpeed * DELTA);
	}

	Vector3 delta = Mouse::Get()->GetMoveValue();

	Rotate(Vector3::Up() * delta.x * rotSpeed * DELTA);
	Rotate(Vector3::Left() * -delta.y * rotSpeed * DELTA);

	localPosition.y = terrain->GetOnGrondPosition(localPosition).y + Radius();

	CAM->SetLocalPosition(localPosition);
	CAM->SetLocalRotation(localRotation);
}

CPP파일은 Quad를 생성하여 이루어진다.

 

Quad는 ViewPort를 사용하는 객체인데. 원래 3D형태의 Object를 사용하나. UI의 경우에는 

 

화면내의 2D객체임으로 2D용으로 생성해놓은 Object이다. 자세한건 후에 후술.

 

Move()함수는 매우 간단하게 구현된 코드인데,

 

현재 위치값을 참조하여 W를 눌렀을 때, 앞으로 이동시키고, y값은 0으로 지정한다 ( Terrain에서 참조받기 때문 )

 

현재 마우스의 MoveValue를 사용해서 Rotation을 보정하고, 현재 Position의 y값을 GrondPosition으로 기입받는다.

 

보정된 값을 CAM의 Position과 Rotation에 기입하여 세팅한다.


Quad

Quad는 객체를 2D처럼 나타내기 위해 만들어놓은 Object이다.

 

기본적으로 srv를 가져와서 평면으로 사용하기 때문에, Float2형태의 size값을 가지며 z가 없다.

class Quad : public GameObject
{
public:
	typedef VertexUV VertexType;

	Quad(Float2 size = { 1, 1 });
	Quad(wstring texturefile);
	~Quad();

	void Render();
private:
	void MakeMesh();
private:
	Mesh<VertexType>* mesh;

	Float2 size;
};
Quad::Quad(Float2 size) : size(size)
{
	mesh = new Mesh<VertexType>();
	MakeMesh();
	mesh->CreateMesh();
}

Quad::Quad(wstring texturefile)
{
	Texture* texture = Texture::Add(texturefile);
	material->SetDiffuseMap(texturefile);
	size = texture->GetSize();

	mesh = new Mesh<VertexType>();
	MakeMesh();
	mesh->CreateMesh();
}

Quad::~Quad()
{
	delete mesh;
}

void Quad::Render()
{
	SetRender();
	mesh->Draw();
}

void Quad::MakeMesh()
{
	Float2 hlafSize(size.x * 0.5f, size.y * 0.5f);

	vector<VertexUV>& vertices = mesh->GetVertices();

	vertices.emplace_back(-hlafSize.x, -hlafSize.y, 0, 0, 1);
	vertices.emplace_back(-hlafSize.x, +hlafSize.y, 0, 0, 0);
	vertices.emplace_back(+hlafSize.x, -hlafSize.y, 0, 1, 1);
	vertices.emplace_back(+hlafSize.x, +hlafSize.y, 0, 1, 0);

	vector<UINT>& indices = mesh->GetIndices();

	indices =
	{
		0, 1, 2, 2, 1, 3
	};

}

코드 또한 간단하다.

 

Mesh를 생성하고, Uv값을 세팅하며,

 

필요시 지정된 srv를 사용할 수있도록 하는것이다.

 

이때 사용된 데이터는 Post를 렌더하는것 임으로,

 

렌더작업시. 환경에서 PostRender시 사용설정을 변경해주어야 한다.

void Environment::SetPost()
{
	blendState[1]->SetState();

	uiViewBuffer->SetVS(1);
	projectionBuffer->Set(orthograpic);
	projectionBuffer->SetVS(2);
}

현재 Environment에서 사용되는 SetPost()함수이다.

 

여기에서 blendState를 [1]을 사용하여. 

void BlendState::Alpha(bool value)
{
    desc.RenderTarget[0].BlendEnable = value;
    desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

    Changed();
}

로 지정하여 사용하고있다.

각각 블렌딩 관련 함수의 기본정리는 링크에 설명해놓았다.

 

이제 사전설정이 완료되었다면, ViewBuffer를 설정하여 현재 사용하는 Render의 뷰포트가 어떤 행렬을 사용해야 하는지 정해주어야 한다.

 

일반적으로 UI의 경우. 정행렬을 사용함으로 참고한다.

    orthographic = XMMatrixOrthographicOffCenterLH(0.0f, WIN_WIDTH,
        0.0f, WIN_HEIGHT, -1.0f, 1.0f);

정행렬 생성함수이다.

 

    Environment::Get()->Set();
    SceneManager::Get()->Render();

    Environment::Get()->SetPost();
    SceneManager::Get()->PostRender();

위설정을 GameManager에서 렌더시 Render를 하고, Post를 위해 사전설정을 하고, PostRender를 사용한다.

 

각각 뷰포트를 따로 쓰기 때문.

 

출력화면.

 

728x90