수학/이득우의 게임 수학 - 실습 예제

게임 월드 탐험 예제

monstro 2026. 1. 28. 17:04
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
반응형