728x90
반응형
- 개요
게임 엔진에 설정된 메인 카메라를 사용하여 월드 공간을 탐험하는 예제를 구성한다
로직에서 카메라의 Transform을 조절하여 카메라가 플레이어를 쫓아다니도록 로직을 구성하였다
또 시각적 효과를 주기 위해 카메라가 한 템포 늦게 따라가는 Lagging 효과를 부여하였다
마지막으로 이전까지 사용한 모델링 행렬 대신 뷰 행렬과 모델링 행렬을 곱한 새로운 행렬을 사용한다
- 예제
...
// 게임 로직을 담당하는 함수
void SoftRenderer::Update2D(float InDeltaSeconds)
{
// 게임 로직에서 사용하는 모듈 내 주요 레퍼런스
auto& g = Get2DGameEngine();
const InputManager& input = g.GetInputManager();
// 게임 로직의 로컬 변수
static float moveSpeed = 200.f;
static float rotateSpeed = 180.f;
static float scaleMin = 15.f;
static float scaleMax = 30.f;
static float scaleSpeed = 180.f;
static float minDistance = 1.f; // 플레이어와 카메라가 일치할 최소 거리
static float lerpSpeed = 2.f; // 플레이어가 카메라를 쫓아가는 속도
// 플레이어에 대한 주요 레퍼런스
GameObject& goPlayer = g.GetGameObject(PlayerGo);
TransformComponent& transform = goPlayer.GetTransform();
// 입력에 따른 플레이어 위치와 크기의 변경
transform.AddPosition(Vector2(input.GetAxis(InputAxis::XAxis), input.GetAxis(InputAxis::YAxis)).GetNormalize() * moveSpeed * InDeltaSeconds);
float newScale = Math::Clamp(transform.GetScale().X + scaleSpeed * input.GetAxis(InputAxis::ZAxis) * InDeltaSeconds, scaleMin, scaleMax);
transform.SetScale(Vector2::One * newScale);
transform.AddRotation(input.GetAxis(InputAxis::WAxis) * rotateSpeed * InDeltaSeconds);
// 플레이어를 따라다니는 카메라의 트랜스폼
TransformComponent& cameraTransform = g.GetMainCamera().GetTransform(); // 카메라의 Transform의 레퍼런스를 가져옴
Vector2 playerPos = transform.GetPosition(); // 플레이어의 Transform에서 위치값을 가져옴
Vector2 cameraPos = cameraTransform.GetPosition(); // 카메라의 Transform에서 위치값을 가져옴
// 카메라에서 플레이어로 향하는 벡터의 크기가 minDistance보다 작은지 비교
// 비교하여 작다면
if ((playerPos - cameraPos).SizeSquared() < minDistance * minDistance)
{
// 플레이어의 위치로 카메라의 위치를 갱신
cameraTransform.SetPosition(playerPos);
}
// 비교하여 작지 않다면
else
{
// 현재 프레임에서 쫓아갈 비율을 ratio 변수에 저장
// 카메라의 위치에서 플레이어의 위치까지의 이동 벡터 * ratio의 연산을 수행하여 카메라가 이동할 위치를 계산
// 계산된 위치로 카메라의 위치를 갱신
float ratio = Math::Clamp(lerpSpeed * InDeltaSeconds, 0.f, 1.f);
Vector2 newCameraPos = cameraPos + (playerPos - cameraPos) * ratio;
cameraTransform.SetPosition(newCameraPos);
}
}
...
매 프레임마다 호출되어 게임을 갱신하는 Update2D 함수의 로직은 위와 같다
카메라는 매 프레임마다 캐릭터와의 거리를 비교하여 플레이어를 따라다닐 수 있도록 구성하였다
...
// 렌더링 로직을 담당하는 함수
void SoftRenderer::Render2D()
{
// 렌더링 로직에서 사용하는 모듈 내 주요 레퍼런스
auto& r = GetRenderer();
const auto& g = Get2DGameEngine();
const auto& texture = g.GetTexture(GameEngine::BaseTexture);
// 배경에 격자 그리기
DrawGizmo2D();
// 렌더링 로직의 로컬 변수
size_t totalObjectCount = g.GetScene().size();
Matrix3x3 viewMatrix = g.GetMainCamera().GetViewMatrix(); // 카메라로부터 뷰 행렬을 가져옴
// 씬을 구성하는 모든 게임 오브젝트의 순회
for (auto it = g.SceneBegin(); it != g.SceneEnd(); ++it)
{
// 게임 오브젝트의 레퍼런스를 얻기
const GameObject& gameObject = *(*it);
if (!gameObject.HasMesh() || !gameObject.IsVisible())
{
continue;
}
// 렌더링에 필요한 게임 오브젝트의 주요 레퍼런스를 얻기
const Mesh& mesh = g.GetMesh(gameObject.GetMeshKey());
const TransformComponent& transform = gameObject.GetTransform();
Matrix3x3 finalMatrix = viewMatrix * transform.GetModelingMatrix(); // 뷰 행렬과 모델링 행렬을 곱하여 정점 변환에 사용할 최종 행렬을 계산
// 게임 오브젝트의 렌더링 수행
DrawMesh2D(mesh, finalMatrix, gameObject.GetColor()); // 메쉬 + 최종 행렬 + 게임오브젝트의 색상을 이용하여 렌더링
// 플레이어의 정보를 화면에 출력
if (gameObject == PlayerGo)
{
r.PushStatisticText("Player Position : " + transform.GetPosition().ToString());
r.PushStatisticText("Player Rotation : " + std::to_string(transform.GetRotation()) + " (deg)");
r.PushStatisticText("Player Scale : " + std::to_string(transform.GetScale().X));
}
}
}
...
게임 월드를 렌더링하는 Render2D 함수의 로직은 위와 같다
카메라로부터 뷰 행렬을 가져오고 가져온 뷰 행렬과 모델링 행렬을 곱하여 최종 행렬을 생성한다
생성된 최종 행렬을 이용하여 정점 변환을 수행하여 오브젝트를 렌더링한다
- 최종 실행 결과

728x90
반응형
'수학 > 이득우의 게임 수학 - 실습 예제' 카테고리의 다른 글
| 벡터의 외적을 활용한 카메라 구현 (0) | 2026.04.29 |
|---|---|
| 3차원 공간의 렌더링 (0) | 2026.03.11 |
| 텍스처 매핑 (0) | 2025.12.17 |
| 정점의 부가 정보를 활용한 무지개 삼각형 만들기 (0) | 2025.12.17 |
| 무게중심좌표를 활용한 와이어프레임의 삼각형 색칠 (0) | 2025.12.03 |