이론 48

타입 객체

왜 씀? 타입 객체 패턴은 다양한 '종류'를 정의할 때 컴파일이나 코드 변경 없이 새로운 타입을 추가하거나 변경할 수 있도록 해준다. 판타지 배경의 RPG 게임을 만든다고 하자. 이 게임의 몬스터는 여러 종족으로 나뉜다. 종족에 따라 최대 체력, 공격 속성 등이 달라진다. OOP 방식으로 구현 고블린, 오크, 용 등은 모두 몬스터의 일종이다. 따라서 몬스터라는 상위 클래스를 만드는 게 자연스럽다. (IS-A 관계) class Monster { public: virtual ~Monster(){} //공격 문구를 받아온다. virtual std::string attack() = 0; }; 하위 몬스터는 다음과 같이 구현될 것이다. class Goblin : public Monster { public: std..

게임 루프

게임 루프 게임 루프는 게임 시간 진행을 유저 입력, 프로세서 속도(!)와 디커플링 한다. 유저 입력은 알겠는데 프로세서 속도와 디커플링 한다는게 무슨 말일까? 굉장히 간단한 게임 루프를 보자. while(true) { processInput(); update(); render(); } processInput에서 유저의 입력을 처리하고, update에서 게임을 시뮬레이션 하고, render에서는 화면을 그린다. 당연한 얘기지만, 컴퓨터가 좋을 수록 1초에 돌릴 수 있는 루프의 횟수가 증가한다. 즉, 게임이 빨리 돌아가게 된다. 즉, 게임의 속도가 프로세서의 속도와 커플링 되어있는 것이다. https://youtu.be/r4EHjFkVw-s 144hz로 게임을 플레이하면 속도가 빨라지는 폴아웃4 어떻게 디..

이중 버퍼

왜쓰나? 여러 순차 작업의 결과를 한 번에 보여주고 싶을 때. 변경 중인 상태에 접근할 수 없게 하고 싶을 때. 코드가 변경하려는 상태를 다시 읽는 경우. 이중 버퍼를 사용하는 가장 대표적인 예는 게임 렌더링이다. class FrameBuffer { public: void clear();//픽셀을 모두 하얀색으로 채운다. void draw(int x, int y);//x,y 픽셀을 검은색으로 바꾼다. }; class Scene { public: void draw(); FrameBuffer& getBuffer(); private: FrameBuffer buffer_; }; 이처럼 FrameBuffer와 화면에 흑백 그림을 그려주는 Scene이 있다고 하자. Scene은 화면에 곰돌이 한 마리를 그린다. v..

텍스처

텍스처? 텍스처 매핑이란 물체의 표면에 컬러를 입히는 기법이다. 픽셀 쉐이더에서 텍스처의 값을 참조해 물체 표면을 표현하는 픽셀의 최종 컬러에 영향을 준다. 대역폭(병목) 텍스처가 병목인 경우는 주로 메모리 대역폭이 모자란 경우이다. 대역폭이란 프로세서가 메모리에 있는 데이터를 가져올 때 최대로 가져올 수 있는 크기를 말한다. PC의 경우에 메모리 대역폭이 문제가 되는 경우는 적지만 모바일 환경의 경우는 다르다. 모바일의 경우에는 성능보다 전력 효율이나 발열등을 신경써야 한다. 메모리도 나름 발열과 전력소비를 많이 하는데 따라서 모바일 하드웨어의 메모리 대역폭은 상당히 작게 설계되는 편이다. 이런 메모리 이슈에는 GPU가 CPU 메모리에서 데이터를 가져오는 경우도 해당한다. 텍스처는 메모리를 많이 사용하..

이론/그래픽스 2022.01.22

서비스 중개자

개요 중개자 패턴은 서비스를 구현한 구체 클래스를 숨긴 채로 어디에서나 서비스에 접근할 수 있게 해 준다. 프로그램에서 메모리 할당, 로그, 난수 생성 등의 시스템은 프로그램 전체에서 사용하는 서비스라고 볼 수 있다. 게임의 경우 오디오 시스템 역시 일종의 서비스일 것이다. UI, 물리엔진, 캐릭터 등 여러 곳에서 오디오를 호출한다. 이러한 경우 정적 클래스나 싱글턴을 사용할 수 있는데 이런 방법은 편한 대신 강한 커플링이 생긴다. (커플링이 생기는 것을 피할 수 없기는 하다.) 전화번호부를 생각해보자. 자신이 전화번호를 바꿨다고 해서 내 번호를 사용하는 모든 사람들에게 전화번호가 바뀌었다고 알리는 편보다 전화번호부에서 자신의 전화번호를 수정하는 편이 훨씬 더 간단하다. 호출하는 쪽에서는 전화번호부에서 ..

이벤트 큐 패턴

이게머임? 이벤트 큐 패턴은 메시지나 이벤트를 보내고 처리하는 시점을 분리하는 패턴이다. (시점의 디커플링) 또한 관찰자 패턴을 멀티 쓰레딩 환경에서 사용할 때 클래스끼리 서로 비동기적으로 상호작용 하도록 할 때 쓸 수 있다. https://tsyang.tistory.com/83?category=1006818#%EA%B4%80%EC%B0%B0%EC%9E%90 디자인 패턴 - 행동패턴 개요 행동 패턴에는 다음 패턴들이 포함되어 있다. (취소선은 다루지 않음) 전략(Strategy) 상태(State) 탬플릿 메서드(Template Method) 명령(Command) 책임 연쇄(Chain of Responsibility) 관찰자 (Observer) 메.. tsyang.tistory.com 기본적으로 관찰차 패..

컴포넌트 패턴

컴포넌트 패턴 컴포넌트 패턴은 한 개체가 여러 분야의 코드를 커플링 없이 다룰 수 있게 해준다. 문제 1 매 업데이트마다 인풋을 받아서 위치를 계산하고 바뀐 위치로 스프라이트를 그리는 Player 클래스가 있다고 하자. void Player::update() { //인풋으로 플레이어의 속도를 결정함. //속도를 이용해 위치를 바꿈 //옮겨진 위치로 플레이어의 스프라이트를 그림. } Player에는 앞으로 여러 기능들이 더 추가 될탠데 그때마다 update가 수정된다. 딱 봐도 코드가 더러워 질 것이라는 예감이 든다. 심지어 각 분야의 작업자들은 다른 분야의 코드를 보게된다. 2 이번에는 GameObject를 상속하는 Zone, Decoration, Prop 오브젝트가 있다고 해보자. Zone은 충돌하지만..

컬링(Culling)

컬링 드로우콜을 줄이기 위해서는 애초에 적은 수의 오브젝트를 렌더링 하면 된다. 이 때 눈에 보이지 않는 오브젝트를 제외함으로써 렌더링할 오브젝트의 수를 줄일 수 있는데, 이처럼 렌더링이 필요하지 않은 오브젝트들을 추려 내는 것을 컬링(Culling)이라 한다. 프러스텀(Frustum) 컬링 대부분의 게임 엔진은 카메라의 뷰 프러스텀(절두체)로 컬링을 수행한다. 즉 저 사다리꼴 영역 안에 들어오거나 걸친 오브젝트만 눈에 보이게 되는데, 이 영역을 완전히 벗어난 오브젝트들은 렌더링 대상에서 제외시키는 것이다. (유니티의 경우 엔진에서 자동적으로 수행) 자유 시점 카메라에서는 카메라의 위치에 따라 렌더링 되는 오브젝트의 갯수가 크게 차이날 수 있다. 이런 경우 프러스텀 컬링에서 Far Clipping Pla..

이론/그래픽스 2021.12.14

디자인 패턴 - 행동패턴

개요 행동 패턴에는 다음 패턴들이 포함되어 있다. (취소선은 다루지 않음) 전략(Strategy) 상태(State) 탬플릿 메서드(Template Method) 명령(Command) 책임 연쇄(Chain of Responsibility) 관찰자 (Observer) 메멘토 (Memento) 중재자 (Mediator) 방문자 (Visitor) 반복자 (Iterator) 인터프리터 (Interpreter) 전략패턴, 반복자패턴은 이미 익숙한 개념이므로 패스, Interpreter는 특정 상황(ex. 문자열 명령어 파싱)에 한정적으로 쓰여서 패스. 상태패턴 2D 횡스크롤 게임이 있다고 가정하다. 캐릭터는 점프, 앉기, 달리기... 등의 여러 동작이 가능하다. 이런 동작들을 구현할 때 많은 예외에 부딪힐 것이다...

디자인 패턴 - 구조

개요 구조 패턴에는 다음의 패턴이 포함된다. Adapter Proxy Facade Decorator Bridge Flyweight Composite 이 글에서는 위 패턴들을 '간단하게' 다룬다. 어답터 패턴 다른 인터페이스에 adapter 클래스를 만들어서 사용하고자 하는 인터페이스와 호환되도록 하는 것이다. 위 다이어그램처럼 외부에서 가져온 ForeignCat은 cry()메서드가 없지만 어댑터를 통해 기존 인터페이스와 호환되게 동작하도록 만들어줄 수 있다. 프록시 패턴 클래스에 접근할 때 프록시 클래스를 통해 접근하는 것. 프록시 클래스에서는 통계나 로그 캐싱등을 해줄 수 있다. class Animal { public: virtual void speak() = 0; }; class Cat final :..