A. 카메라

카메라는 컴포넌트 기반으로 만들어져 객체(Actor)에 부착되며, 해당 객체의 위치를 기준으로 씬(Scene)을 렌더링합니다.


1. 카메라 생성

a. 카메라 컴포넌트 생성

카메라는 Component 클래스를 상속받아 구현되며, 이 컴포넌트는 Actor의 일부로 추가됩니다.

관련 코드
class CameraComponent : public Component
{
public:
    CameraComponent();
    virtual ~CameraComponent() override;

    virtual void BeginPlay() override;
    virtual void TickComponent() override;
    virtual void Render(HDC hdc) override;
};
  • CameraComponent: 카메라의 역할을 수행하는 클래스.
  • 상속 구조:
    • Component: 모든 컴포넌트의 기본 클래스.
    • CameraComponent: Component를 상속받아, 카메라 기능을 수행.

초기화
CameraComponent::CameraComponent() {}
CameraComponent::~CameraComponent() {}
  • 생성자와 소멸자를 정의하지만, 초기화 로직은 추가하지 않음.
업데이트 로직
void CameraComponent::TickComponent()
{
    if (_owner == nullptr)
        return;

    Vec2 pos = _owner->GetPos();

    // TEMP: 카메라 위치 제한 설정
    pos.x = ::clamp(pos.x, 400.f, 3024.f - 400.f);
    pos.y = ::clamp(pos.y, 300.f, 2064.f - 300.f);

    GET_SINGLE(SceneManager)->SetCameraPos(pos);
}
  • _owner: 이 컴포넌트를 소유한 Actor를 참조.
  • GetPos(): Actor의 현재 위치를 가져옵니다.
  • clamp: 화면 경계 밖으로 카메라가 이동하지 않도록 제한.
  • SetCameraPos: 씬 매니저(SceneManager)에 현재 카메라 위치를 업데이트.

b. SceneManager에 카메라 위치 업데이트

관련 코드
class SceneManager
{
public:
    Vec2 GetCameraPos() { return _cameraPos; }
    void SetCameraPos(Vec2 pos) { _cameraPos = pos; }

private:
    Vec2 _cameraPos = { 400, 300 }; // 카메라 초기 위치
};
  • GetCameraPos: 현재 카메라 위치를 반환.
  • SetCameraPos: 카메라 위치를 설정.
작동 방식
  • CameraComponent에서 카메라 위치를 계산하고 SceneManager로 전달.
  • SceneManager는 이 위치를 기반으로 씬의 렌더링을 조정.

c. Player에게 카메라 컴포넌트 추가

관련 코드
Player::Player()
{
    _flipbookUp = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveUp");
    _flipbookDown = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveDown");
    _flipbookLeft = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveLeft");
    _flipbookRight = GET_SINGLE(ResourceManager)->GetFlipbook(L"FB_MoveRight");

    // 플레이어에 카메라 컴포넌트 추가
    CameraComponent* camera = new CameraComponent();
    AddComponent(camera);
}
  • 플레이어 객체(Player) 생성 시 카메라 컴포넌트를 추가.
  • AddComponent: 컴포넌트를 Actor에 추가하는 함수.
컴포넌트 추가 메서드
void Actor::AddComponent(Component* component)
{
    if (component == nullptr)
        return;

    component->SetOwner(this); // 컴포넌트에 소유주(Actor) 설정
    _components.push_back(component); // 컴포넌트를 벡터에 추가
}

d. Actor 렌더링에서 컴포넌트 처리

관련 코드
void Actor::Render(HDC hdc)
{
    for (Component* component : _components)
    {
        component->Render(hdc);
    }
}
  • Actor가 가진 모든 컴포넌트의 Render 메서드를 호출.
  • CameraComponent는 렌더링 기능을 가지지만 현재 구현에서는 빈 상태.

2. 이미지 위치 보정

카메라 위치에 따라 플레이어와 배경의 렌더링 위치를 조정하여, 카메라가 이동할 때 화면 중앙이 적절히 업데이트되도록 처리.


플립북 렌더링에서 보정

관련 코드
void FlipbookActor::Render(HDC hdc)
{
    if (_flipbook == nullptr)
        return;

    Vec2 cameraPos = GET_SINGLE(SceneManager)->GetCameraPos();

    ::TransparentBlt(hdc,
        (int32)_pos.x - info.size.x / 2 - ((int32)cameraPos.x - GWinSizeX / 2),
        (int32)_pos.y - info.size.y / 2 - ((int32)cameraPos.y - GWinSizeY / 2),
        info.size.x,
        info.size.y,
        info.texture->GetDC(),
        (info.start + _idx) * info.size.x,
        info.line * info.size.y,
        info.size.x,
        info.size.y,
        info.texture->GetTransparent());
}
  • cameraPos: 현재 카메라의 위치를 가져옵니다.
  • 화면 중심 보정:
    • (int32)cameraPos.x - GWinSizeX / 2
    • (int32)cameraPos.y - GWinSizeY / 2
  • 이 보정을 통해 화면 중앙에 카메라를 기준으로 오브젝트가 위치하도록 조정.

배경 렌더링에서 보정

관련 코드
void SpriteActor::Render(HDC hdc)
{
    Vec2 cameraPos = GET_SINGLE(SceneManager)->GetCameraPos();

    ::BitBlt(hdc,
        (int32)_pos.x - size.x / 2 - ((int32)cameraPos.x - GWinSizeX / 2),
        (int32)_pos.y - size.y / 2 - ((int32)cameraPos.y - GWinSizeY / 2),
        size.x,
        size.y,
        _sprite->GetDC(),
        _sprite->GetPos().x,
        _sprite->GetPos().y,
        SRCCOPY);
}

B. 레이어

1. 레이어 필요성

  • 레이어를 사용하지 않으면 렌더링 순서가 코드 순서에 의존.
  • 예: 배경보다 플레이어가 먼저 렌더링되면 플레이어가 배경 뒤로 가려짐.

2. 레이어 구현

a. 레이어 타입 정의

enum LAYER_TYPE
{
    LAYER_BACKGROUND,
    LAYER_OBJECT,
    LAYER_UI,
    LAYER_MAXCOUNT
};
  • 레이어는 enum으로 정의.
  • Actor는 특정 레이어에 속하며, DevScene에서 레이어별로 관리.

b. DevScene의 레이어별 관리

관련 코드
vector<Actor*> _actors[LAYER_MAXCOUNT];

void DevScene::AddActor(Actor* actor)
{
    if (actor == nullptr)
        return;

    _actors[actor->GetLayer()].push_back(actor);
}

void DevScene::Render(HDC hdc)
{
    for (const vector<Actor*>& actors : _actors)
        for (Actor* actor : actors)
            actor->Render(hdc);
}
  • _actors: 레이어별로 Actor를 저장.
  • 렌더링 순서: LAYER_BACKGROUNDLAYER_OBJECTLAYER_UI.

profile
李家네_공부방

0개의 댓글