728x90

1. 컴포넌트 패턴 정의

  • 한 개체가 여러 분야를 서로 커플링 없이 다룰 수 있게 한다.

 

2. 커플링 된 함수

if ( CollidingWithFloor() && ( GetRenderState() != ERanderState::INVISIBLE ) )
{
    PlaySound( ESound::HIT_FLOOR );
}
  • 물리 ( CollidingWithFloor() ), 그래픽 ( GetRenderState() ), 사운드 ( PlaySound() )가 커플링 된 소스 코드
  • 소스 코드 수정을 위해서는 위 3가지 항목을 전부 알아야 하기에 유지보수가 힘들다.

3. 커플링 된 클래스

class GameObject
{
private:
    static const int WALK_ACCELERATION = 1;

    int Velocity;
    int X, Y;

    FVolume Volume;

    FSprite SpriteStand;
    FSprite SpriteWalkLeft;
    FSprite SpriteWalkRight;

public:
    GameObject() : Velocity( 0 ), X ( 0 ), Y ( 0 ){}
    void Update( FWorld& InWorld, FGraphics& InGraphics )
    {
        // 입력에 따라 주인공의 속도를 조절한다.
        switch ( Controller::GetJoystickDirection() )
        {
            case Direction::Left:
            Velocity -= WALK_ACCELERATION;
            break;

            case Direction::Right:
            Velocity += WALK_ACCELERATION;
            break;
        }

        // 속도에 따라 위치를 바꾼다.
        X += Velocity;
        InWorld.ResolveCollision( Volume, X, Y, Velocity );

        // 알맞은 스프라이트를 그린다
        FSprite* sprite &SpriteStand;
        if ( Velocity < 0 )
            sprite = &SpriteWalkLeft;
        else if ( Velocity > 0 )
            sprite = &SpriteWalkRight;
        
        InGraphics.Draw( *sprite, X, Y );
    }
};
  • Update 함수 안에 물리엔진 / 그래픽 엔진 등 함수들이 커플링 되어 있다.

 

3. 분야별로 컴포넌트화

class InputComponent
{
private:
    static const int WALK_ACCELERATION = 1;

public:
    void Update( GameObject& InGameObject )
    {
        // 입력에 따라 주인공의 속도를 조절한다.
        switch ( Controller::GetJoystickDirection() )
        {
            case Direction::LEFT:
            InGameObject.Velocity -= WALK_ACCELERATION;
            break;

            case Direction::RIGHT:
            InGameObject.Velocity += WALK_ACCELERATION;
            break;
        }
    }
};

class PhysicsComponent
{
private:
    FVolume Volume;

public: 
    void Update( GameObject& InGameObject, FWorld& InWorld )
    {
        InGameObject.X += InGameObject.Velocity;
        InWorld.ResolveCollision( Volume, InGameObject.X, InGameObject.Y, InGameObject.Velocity );
    }
};

class GraphicsComponent
{
private:
    FSprite SpriteStand;
    FSprite SpriteWalkLeft;
    FSprite SpriteWalkRight;

public:
     void Update( GameObject& InGameObject, FGraphics& InGraphics )
    {
        // 알맞은 스프라이트를 그린다
        FSprite* sprite = &SpriteStand;
        if ( InGameObject.Velocity < 0 )
            sprite = &SpriteWalkLeft;
        else if ( InGameObject.Velocity > 0 )
            sprite = &SpriteWalkRight;
        
        InGraphics.Draw( *sprite, InGameObject.X, InGameObject.Y );
    }
};

class GameObject
{
private:
    InputComponent Input;
    PhysicsComponent Physics;
    GraphicsComponent Graphics;

public:
    int Velocity;
    int X, Y;

public:
    GameObject() : Velocity( 0 ), X ( 0 ), Y ( 0 ){}
    void Update( FWorld& InWorld, FGraphics& InGraphics )
    {
        Input.Update( *this );
        Physics.Update( *this, InWorld );
        Graphics.Update( *this, InGraphics );
    }
};
  • 각 분야별로 입력, 물리, 그래픽을 컴포넌트화 하여 분리한다.

 

4. 컴포넌트 추상화

class InputComponent
{
public:
    virtual ~InputComponent() {}
    virtual void Update( GameObject& InGameObject ) = 0;
};

class PlayerInputComponent : public InputComponent
{
private:
	static const int WALK_ACCELERATION = 1;

public:
	virtual void Update( GameObject& InGameObject ) override
	{
		// 입력에 따라 주인공의 속도를 조절한다.
		switch ( Controller::GetJoystickDirection() )
		{
			case Direction::LEFT:
			InGameObject.Velocity -= WALK_ACCELERATION;
			break;

			case Direction::RIGHT:
			InGameObject.Velocity += WALK_ACCELERATION;
			break;
		}
	}
};
  • 추상 상위 클래스를 만들어, 사용자에 맞춰 컴포넌트를 정의하여 사용할 수 도 있다.
반응형

+ Recent posts