posted by REDFORCE 2017. 5. 25. 16:51

이번 글에서 다룰 명령 패턴 내용은 실행취소와 재실행에 대한 내용입니다.


어떤 명령 객체가 실행할 수 있다면, 이를 실행취소 할 수 있게 만드는것도 어렵지 않습니다.

게임개발 툴 같은곳에서는 필수적으로 지원이 되야하는 기능입니다. 만약 이 기능이 지원되지 않는다면....


(기획자가 당신을 죽이려들지도...)



그냥 실행취소 기능을 구현하려면 굉장히 어렵습니다. 그러나 명령패턴을 활용하면 이를 쉽게 만드는게 가능합니다. 예를 들어서 턴제 게임에서 이동 취소 기능을 추가한다고 하겠습니다.


이미 명령 객체를 2편에서 명령 객체를 이용해서 입력 처리를 추상화해둔 덕분에, 플레이어 이동도 명령에 캡슐화되어 있습니다. 이제 어떤 유닛을 옮기는 명령을 생각해보도록 하겠습니다.



MoveUnitCommand 클래스는 이전 에졔와 약간 다르게 생겼습니다.

이전 에졔에서는 명령에서 변경하려는 액터와 명령 사이를 추상화로 격리시켰지만 이번에는 이동하려는 유닛과 위치 값을 생성자에서 받아서 명령과 명시적으로 바인드되어 있습니다.

MoveUnitCommand 명령 인스턴스는 '무엇인가를 움직이는' 보편적인(언제든지 써먹을 수 있는) 작업이 아니라 게임에서의 구체적인 실제 이동을 담고있습니다.


2편에서 다룬 에졔 같은 경우, 어떤 일을 하는지를 정의한 명령 객체 하나가 매번 재사용 됩니다.

입력 핸들러 코드에서는 특정 버튼이 눌릴 때마다 여기에 연결된 명령 객체의 execute() 를 호출 했었습니다.


이번에 만든 명령 클래스는 특정 시점에 발생될 일을 표현한다는 점에서 더 구체적입니다.

이를 테면, 입력 핸들러 코드는 플레이어가 이동을 선택할 때마다 명령 인스턴스를 생성해야합니다.



Command 클래스가 일회용이라는 게 장점이라는 걸 이제 명령을 취소할 수 있도록 순수가상함수 undo() 를 정의하여 보면 알 수 있습니다.



Undo( ) 에서는  execute( ) 에서 변경하는 게임상태를 반대로 바꿔주면 됩니다. 이제 MoveUnitCommand 클래스에 실행취소 기능을 넣어보겠습니다.




잘보면 MoveUnitCommand  클래스에 상태가 몇 개 추가되었습니다. 즉 유닛이 이동한 후에는 이전 위치를 알수 없기 때문에, 이동을 취소할 수 있도록 이전 위치를 xBefore_, yBefore_멤버 변수에 따로 저장하도록 합니다.


이제 플레이어가 이동을 취소 할 수 있게 하려면 Ctrl + z 키를 눌러서 취소 하는 것과 같이 undo() 명령을 수행하면 됩니다. 만약 다시 재실행을 하고 싶다면 redo() 함수를 만들어서 사용하면 가능합니다.


끝으로 여러단계의 실행취소를 지원하는 것도 어렵지 않습니다. 방법은 가장 최근 명령만 기억하는대신, 명령 목록을 유지하고 '현재' 명령이 무엇인지만 알고 있으면 됩니다.

유저가 명령을 실행하면, 새로 생성 된 명령을 목록 맨 뒤에 추가하고, 이를 '현재' 명령으로 기억하면 됩니다.

posted by REDFORCE 2017. 5. 18. 22:14

#1. Engine System

 + WinMain - EngineSystem

 + EngineCore

 + EngineError

 + MainNode


#2. FrameWork

 + Grahpics

 + Image - SpriteData

 + Layer  

 + Input (현재 글)

 + Game

 + Manager

 + Game Interface

 + Utility


#3. Testing Module

 + 2D Image Test

 + 2D Animation Test

 + Game UI Test


-----------------------------------------------------------------------


이번글에서 설명 할 내용은 Input Class 입니다.


Input 클래스는 엔진에서의 모든 키입력 처리에 대한 것을 담당하는 클래스입니다.


일반적인 키보드 입력, 마우스 입력 부터 XBox Pad의 입력에 대한 처리를 담당합니다.




먼저 헤더에서의 주요 내용들을 살펴보도록 하겠습니다.


헤더에서 다룰 내용 목록은 다음과 같습니다.


1. 키 입력을 위한 주요 변수들

2. Input 클래스의 주요 함수 목록 


본 글에서는 자세한 게임패드 입력처리에 대한 설명은 하지 않습니다.

게임패드 입력처리에 대한 자세한 내용은 다음에 기회가 되면 다루도록 하겠습니다.

(#include <XInput>제목으로 별도의 포스팅을 통해 다룰 예정입니다.)




1. 먼저 Input.h 의 상단에 위치한 내용들을 보도록 하겠습니다.



 (1) namespace inputNS를 보시면 사용 될 모든 키들에 대한 값들을 위해 KEYS_ARRAY_LEN이 있습니다. 사용 할 키들의 사이즈 크기라 보시면 됩니다. (즉, 256 개의 키를 지원)

 (2) 다음 키다운 이나 눌러졌다를 판단할 용도의 KEYS_DOWN / KEYS_PRESSED 플래그

 (3) 마우스에 대한 플래그 값 MOUSE와 텍스트 입력에 대한 플래그 값 TEXT_IN 플래그

 (4) 모든 키들을 Clear시킬 용도로 각 플래그 값들을 합친 KEYS_MOUSE_TEXT 플래그


그리고 그 아래에는 게임 패드를 사용하는 것들에 대한 키 플래그값들이 나열되어 있습니다.

게임패드에 대한 입력을 처리할 목적으로 선언되어 있으나 패드를 지원하는 게임을 만들 게 아니라면 딱히 사용할 일은 없습니다.


게임 패드에 대한 선언은 본 글에서는 생략하고 추후 XInput에 대한 것을 다룰 때 다시 설명하도록 하겠습니다.



다음, Input 클래스에서 키 입력 처리를 위해 사용 되어지는 주요 변수들 입니다.


(private: 접근한정자 안에 선언 된 주요 변수들을 먼저 코드로 올렸습니다. 실제 전체 코드는 public: 영역도 포함하여 최 하단에 업로드 되어있습니다.)



 (1) keysDown[KEYS_ARRAY_LEN] / keysPressed[KEYS_ARRAY_LEN] (키 입력 여부를 판단할 목적의 bool 변수)

 (2) bool mouseWheelRoll / Rollup/ RollDown (마우스 휠을 굴렸을 때의 이벤트 판단목적)

 (3) std::string textIn (텍스트 입력값들을 저장할 목적)

 (4) char charIn (텍스트 입력 시 한 글자 값들을 저장)

 (5) bool newLine (줄바꿈 여부를 판단할 목적)

 (6) int mouseX / Y (현재 마우스 커서의 x,y 위치)

 (7) int mouseRawX / Y (현재 마우스커서의 고감도 x, y 위치)

 (8) RAWINPUTDEVICE Rid[1] (고감도 마우스 지원 여부 판단 목적의 변수)

 (9) bool mouseCaptured (마우스 위치 캡쳐 목적의 플래그 값)

 (10) bool mouseL/M/RButton (마우스 좌/우/중앙 키 입력 플래그 값)

 (11) bool mouseX1/X2Button (마우스 특수버튼 1,2 키 플래그 값)

 (12) ControllerState controllers[MAX_CONTROLLERS] (게임 패드 이용 시 사용하는 플래그 값)


들로 주요 변수들이 이루어져 있습니다.


일반적인 게임 키처리에 대한 변수들과 동일한 구조 형태라 아마 이름만봐도 아 저변수가 무슨용도구나 하고 이해하시는데는 불편함이 없을거라 생각합니다.



그럼 마지막으로 각 키입력에 대한 함수들의 구조를 보겠습니다.


2. 주요 함수 목록



지금 위에 언급된 함수 외에도 게임패드관련 함수가 상당히 많이 있습니다만, 분량이 너무 길어지는 관계로 위 코드에는 올리지 않았습니다. 최하단 전체 코드에는 게임패드 관련 함수도 같이 들어있습니다.


헤더에서 함수가 뭐 이렇게 많아!? 하고 겁먹으실 필요는 없습니다.

어짜피 엔진을 쓰면서 사용하게 될 함수는 8~90% isKeyDown / wasKeyPressed 밖에 없으니까요. 게임패드 관련 함수를 뺏음에도 상당히 부담이 가신다면 아래와 같이 간단히 이런 게 있다 라고만 보시면 될 것 같습니다.


 (1) 생성자 / 소멸자

 (2) KeyDown / Up / In (키입력에 대한 판단 함수)

 (3) isKeyDown (키가 눌러졌냐~? 라고 물어보는 함수)

 (4) wasKeyPressed (최근 프레임 1~2사이에 키가 눌려졌냐~? 라고 물어보는 함수)

 (5) anyKeyPressed (아무키나 눌러졌었냐~? 라고 물어보는 함수)

 (6) clearKeyPressed (눌려진적이 있는 키를 다시 false로 초기화 하는 함수)

 (7) mouseWheel In / Up / Down (마우스 휠이 굴려졌을때 위로굴렸냐 아래로 굴렸냐 체크하는 함수)

 (8) clear / clearAll / clearTextIn 각각 키 입력에 대한 Clear 함수

 (9) getTextIn / getCharIn (문장 / 한 글자 입력 시 내용 받아오는 함수)

 (10) set/ get Mouse L/M/R/X Button (마우스 키 입력 또는 받아오는 함수)

 (11) getMouseX / Y , getMouseRawX /Y (마우스 좌표 받아오는 함수)


키 입력에 대한 처리를 하는 함수들은 위와 같이  11가지가 있습니다.

결과적으로는 모두 다 사용하는 함수들이기 때문에 대충 어떤목적에 사용한다 라는 것만 알고 넘어간 뒤 엔진을 사용하면서 쓰다보면 자연스레 본인이 쓰고 있는 모습을 볼 수 있습니다.


자세한 각 함수들에 구현 내용은 .cpp로 이어서 적도록 하겠습니다.



아래는 전체 헤더파일 내용입니다.



'MyProject > SephyEngine' 카테고리의 다른 글

June_Engine #3_LayerManager Class .cpp  (0) 2017.04.21
June_Engine #3_LayerManager Class .h  (0) 2017.04.21
June_Engine #3_Layer Class  (0) 2017.04.21
June_Engine #3_Image Class .cpp (2)  (0) 2017.04.20
June_Engine #3_Image Class .cpp (1)  (0) 2017.04.19
posted by REDFORCE 2017. 5. 5. 01:42


명령 패턴 두 번째글 입니다. 혹시나 첫 번째 글을 보시지 않은 분들이 계시다면

다음 링크를 눌러서 바로 가실 수 있습니다. (명령 패턴 : 입력 키 변경)


2. 액터에게 지시하기


명령 패턴을 활용한 방법 두 번째 내용은 액터에게 지시하기 입니다.


이전 글에서 정리한 내용은 순전히 Command 클래스로 만든 Jump() 나 FireGun() 과 같은 전역 함수가 플레이어 캐릭터 객체가 사용할 것임을 암시적으로 찾아서 활용해야 한다는 점이 가정에 깔려 있기 때문에, 플레이어만 사용할 수 있다라는 제한이 있습니다.



그러나 꼭 플레이어만 아닌 어떤 몬스터나 캐릭터나 AI가 움직이는 NPC들도 

Jump() 나 FireGun() 과 같은 동작을 한다면??


일일이 모든 캐릭터에게 위와같은 Command 클래스를 넣어줘야 한다면 그건 그것나름대로 동작은 가능하지만 불편할 것 같습니다.


그래서 행동 자체를 실체화 시킨 것에서 행동할 액터를 받아오게끔 만드는 방법이 있습니다.



위에서 GameActor는 게임 월드를 돌아다니는 캐릭터를 대표하는 '게임 객체' 클래스라 보시면 됩니다. 이제 Command를 상속받은 클래스는 execute()가 호출될 때 GameActor 객체를 인수로 받기 때문에 원하는 액터의 메서드를 호출 할 수 있습니다.


위 말은 이제 원하는 액터의 메서드를 호출 하게끔 다음과 같이 Command 클래스가 이용가능해진다는 뜻 입니다.



코드를 보는것처럼 이제 JumpCommand 클래스 하나로 게임에 등장하는 어떤 캐릭터라도 점프를 할 수 있게끔 가능해졌습니다.


이제 입력 핸들러에서 입력을 받아 적당한 객체의 메서드를 호출하는 명령 객체를 연결하는 것을 만들 차례입니다. 먼저 InputHandler()에서 명령 객체를 반환하도록 변경합니다.



다음으로 명령 객체를 받아서 플레이어를 대표하는 GameActor 객체에 적용하는 코드가 필요합니다.



이렇게 하면 액터(actor)가 플레이어 캐릭터라면 유저 입력에 따라 동작하기 때문에 이전 글에서 다룬 내용과 기능상 다를 게 없지만, 명령을 실행할 때 액터만 바꾸면 플레이어가 게임에 있는 어떤 액터라도 제어 할 수 있게 됩니다.


일반적으로 플레이어가 AI를 제어하는 일은 많이 없지만, 꼭 AI를 제어하는 기능이 아니더라도 위와 같이 액터를 제어하기 위한 AI를 만드는 상황에서도 많은 활용이 되도록 설계가 가능합니다.


posted by REDFORCE 2017. 5. 2. 17:44

본 글은 아래의 교재를 참고하여 정리한 내용입니다.


책 이름 : 게임프로그래밍 패턴 (한빛미디어)

저자 : 로버트 나이스트롬

옮김 : 박일


------------------------------------


GoF에 정의 한 명령 패턴을 따르면 명령패턴이란.


요청자체를 캡슐화하는 것 입니다. 이를 통해 요청과 서로 다른 사용자를 매게변수로 만들고, 요청을 대기시키거나 로깅하며, 되돌릴 수 있는 연산을 지원합니다.(GoF의 디자인 패턴. 311쪽)


위 말만 들어서는 잘 이해가 안가는데? 하고 궁금해할 수 있습니다.


그래서 명령 패턴을 한 줄로 다시 요약해보자면, 

명령 패턴은 메서드 호출을 실체화(reify)한 것이다.


라고 할 수 있습니다. 대체 메서드 호출을 실체화 했다라는게 무슨말일까요?




바로 메서드 자체를 어떤 한 객체로 만들었다는 뜻 입니다. 메서드는 우리가 알다시피 어떤 함수형태로 행위를 하는 녀석이지만, 이 행위의 내용을 바꿀수는 없습니다. 그러나 이 행위 자체를 어떤 객체로 만들어서 실체화 시키면 행위의 내용 자체를 다른 것으로 바꿔서 가능하게끔 하는 것이 바로 명령 패턴입니다.


1. 입력키 변경


그럼 명령 패턴을 활용하는 첫 번째 예를 보겠습니다.


보통 모든 게임은 입력(Input)을 통해 어떤 출력(Output)이 나오게 되는데요.

가장 보편적인 입력 방식인 키보드와 마우스를 누르는 코드가 다음과 같이 있다고 치겠습니다.



일반적으로 이런 형태의 함수로 이루어진 입력 핸들러가

게임 루프 과정에서 매 프레임마다 호출되어 입력에 대한 것을 확인하게 됩니다.


그러나 만약 사용자가 입력키에 대한 변경을 하려면 위의 키가 교체 가능하도록 키입력에 대한 어떤 객체가 필요하게 됩니다. 이 때 명령 패턴을 넣어서 한번 키입력을 변경하도록 만들어보겠습니다.


먼저, 게임에서 할 수 있는 행동을 실행할 수 있는 공통 상위 클래스를 먼저 정의합니다.


다음, 각 행동별로 하위 클래스를 만듭니다.



그리고 입력 핸들러코드로 각 버튼별로 Command 클래스 포인터를 저장합니다.



이렇게 하면 입력 처리는 이제 다음 코드로 위임됩니다.



여기까지가 Input 키 명령 패턴을 이용한 입력키 변경을 위한 방법입니다.

보시다시피 어떤 입력키에 대한 메서드 자체를 클래스로 실체화하여 입력키 값이 변경되더라도

어떤 행동을 한다라는 메서드는 동일하게 수행이 되는 구조가 되는 것이지요.


위 방법이 명령패턴의 핵심입니다만, 이것만 봐서 만족할 순 없겠지요!

다음 글에서 명령 패턴을 더 활용하는 글을 확인하도록 하겠습니다.


마무리는 이 글을 읽으셨을 분들께 감사드리며 짤방 투척!



posted by REDFORCE 2017. 4. 27. 00:28

4. ㅁㅁ을 하자.



시작부터 강렬한 짤방을 올려보았습니다.


다소 여성분들에겐 푸핰! 하고 난 여기서 빠져나가겠어!!!!!!


하실 수도 있겠지만...

(뒤 늦게나마 = _=죄송합니다...)




아무튼..


네 번째로 언급할 내용은 


4. 설계를 하자. 


입니다.



만약 이 글을 보시는 분이 프로그래머 분이라면, 혹 프로젝트를 진행하기 앞서


어떤 클래스가 어떤 메소드(함수)들을 내포하고 수행할 것인지

설계 해보신 적이 있으실 겁니다.



팀 프로젝트를 진행하는데 있어서도 위와 같은 생각을 하는 것은 똑같다고 생각합니다.


제가 "설계를 하자" 라고 언급하였는데, 왜 그랬을까요~?



이유는 팀 프로젝트에서 각 팀원들이 맡은 역할을 잘 분배하고 잘 수행하기 위해서 입니다.


제가 몸담고 있는 '게임' 이라고 하는 분야를 포커스로 이야기를 진행하도록 하겠습니다.



'게임' 이라고 하는 분야는 옛날엔 오락이었을 뿐이었지만,


현재는 '예술' 이라고도 칭하는 경지에 이르렀습니다.


디자인/개발/음악/기획/시나리오 등 많은 분야의 사람들이 모여서 같이 어떤 창작 활동을 하기 때문에 저는 예술 그 이상의 분야라 생각합니다.



그런데, 왜 팀 프로젝트에서 설계를 할까요?


간단한 상황을 들어보도록 하겠습니다.



어떤 미소녀 캐릭터가 있고 사운드 효과들이 포함되어 있으며 스토리가 포함된 액션 게임을 만든다고 칩시다.


시나리오 작가 : 열심히 미소녀 캐릭 액션 게임 스토리를 상상했습니다.

디자이너A : 주인공을 만들기 위해 피카츄를 그렸습니다.

디자이너B : 배경을 그렸습니다.

음원 제작가 : BGM과 이펙트 소리들을 만들었습니다.

프로그래머A : 대선 준비를 했습니다.

프로그래머B : 치킨만 먹었습니다.


자...우리는 여기서 무엇을 알수있는가? 하면.



네 안됩니다!!


안되요!! 뭘 해달라는거야!!


어떤 미소녀 캐릭터가 있는건 알겠는데, 스토리는 작가가 알아서 한다치고

디자이너와 프로그래머 및 음원 제작가는 대체 무엇을 만들었을까요...


알 수가 없습니다.


그냥 프로그래머 B가 치킨먹을때 같이 먹었을거 같아요.



여러분. 팀 프로젝트를 할 때는 항상 기본적인 육하 원칙을 지켜서 진행해야합니다.


1. 언제

2. 어디서

3. 어떻게

4. 무엇을

5. 누가

6. 왜


기본적으로 위 사항을 딱 한번만이라도 생각해본다면 여러분은 팀프로젝트를 진행할 수 있습니다.


일일이 모든 사항을 언급해서 적진 않겠습니다만, 간단히 요약해서 정리하자면

팀 프로젝트를 진행 하실 땐, 항상 누가 무엇을 한다. 라는 것을 지적해서 정해야 합니다.



따라서, 팀 프로젝트를 진행할 땐 항상 설계를 해야하는데,


어떤 설계를 해야하는가? 에 대해서 설명하겠습니다.



1. 일주일 간 진행할 목표를 정하자.


2. 다다음 회의 내용을 생각하자.  (다음이 아닙니다! 다다음 이에요!)


3. 스케줄을 만들자.


입니다.



첫 번째 항목부터 보도록 할까요.


1. 일주일 간 진행할 목표를 정하자.



프로젝트를 진행할 때 최종 목표는 이미 무엇을 만들자! 라는 식으로 정해져 있습니다.


그러면 마지막 최종 목표에 도달하기 위해 무엇들이 필요한지를 살펴봐야합니다.



제가 겪었던 한 예를 들어서 설명하겠습니다.


어떤 프레임워크를 만들기 위해 여러가지 어떤 내용들이 있는지 기능 별로 나눠서 포스트잇으로 적어보던 중 생각보다 많은 내용들이 등장한다는 것을 알게 되었던 적이 있습니다.



이 기능들이 모여서 결과적으론 최종 목표에 도달한다는 것도 다시 한번 눈으로 확인할 수도 있었지요.


그리고 이렇게 나눠놓은 리스트중에서 우선순위를 잡습니다.


우선순위 별로 포스트잇을 정렬시켜보니 위 그림처럼 나왔었습니다.



우선순위의 가중치는 여러 요인이 될 수 있습니다.


내가 지금 할 수 있는 것? 지금 당장해야 하는 것?

A 기능을 만들기 위해 B와 C가 미리 구현이 되어야한다는 점? 등등..



어쨋든 중요한 점은 이렇게 나눠본 프로젝트의 내부 항목들 중에서


이번 주에는 1~2번 기능을 구현하자. 라고 정하고 한 주 동안 개발을 시작하는 것 입니다.



만약 다음주까지 이 기능을 구현하지 못했다면 이 기능을 만드는데는 

"시간이 좀 더 필요하다" 라는 점을 경험할 수 있게 됩니다.


그리고 다음에 또 이와 같이 비슷한 기능을 만들 때 어느정도의 시간이 필요하겠구나

라는 것을 가늠할 수 있게 될 수 있습니다.


이런식으로 1~2 주 정도 진행하다보면 프로젝트를 진행하는데 감이 많이 잡히게 됩니다.


팀 프로젝트 단위에서도 마찬가지로 각자 맡은 개발분야에서 이런식으로 약속한 기간에 맞춰 회의 할 때마다 중간 점검을 하는식으로 진행을 하는 것이 좋습니다.



2. 다다음 회의 내용을 생각하자


왜 다음 회의 내용이 아닌 다다음 회의 내용을 생각하자 라고 했을까요.


사실 다음 회의 내용은 이번 주에 자신이 맡은 개발 파트가 어떻게 진행되냐에 따라

다음 개발 계획으로 진행이 될 것인지 말 것인지 의논하게 됩니다.



그래서 다다음 회의 내용을 생각하자 라고 한 것 입니다.


그러면 어짜피 다음 회의 내용을 생각한거랑 같은거 아닌가?

라고 생각이 드실텐데, 또 그것은 아닙니다.



그럼 대체 뭘 생각하란거야? 라고 느끼실텐데요.


한가지 상황을 통해 예를 들어보겠습니다.



1 주(진행중) - 어떻게 될지 모른다...다 만들수 있을지 없을지...(A 기능을 구현 중)

2 주 - B 기능에 대해서 생각해봐야한다.


그럼. 3 주 - ?????


무엇을 준비해야할까?


바로. 피드백 입니다.


다다음 회의 내용을 위해 생각할 것은 프로젝트에 대한 개발 내용보다는 


(1)이전에 했던 작업물에 대한 다른사람들을 위한 피드백 또는


(2)내가 하고있는 작업물에 대한 내용 정리입니다.



왜 이것을 해야할까요?



팀 프로젝트의 목적 상. 본래 어떤 목표를 위해 개발을 하는 것이지만.


결과만 바라보고 개발 과정을 정리하지 않으면


뒤에는 큰 후회만 남습니다.



왜 냐구요?


그 프로젝트가 끝까지 완수 될지 안될지 누가알아요!!!


만약 프로젝트가 중간에 파토가 나버리면 쏟아 부었던 노력에 대한 보상은 누가해주나요!?


아무도 안해줍니다. 없어요. 누가 해줄까요. 사장님? 팀장님?


물론 회사 라면 월급받고 일할테니 나의 경력과 돈이 생기겠지요.


하지만, 상업적이거나 회사에서 일하는 팀 프로젝트가 아니라면, 그 누구도 프로젝트가 파토났을 때 보상을 해줄 사람이 없습니다.


따라서, 다다음 회의 내용을 위해 피드백을 준비하라 라고 한 이유는


 (1) 팀 프로젝트가 계속 활발히 개발되어지고 있으며, 우리는 할 수 있을 거야 라는 확인하는 점

 (2) 중간 중간 내용을 정리하고 점검하며 내 실력을 쌓고 

 (3) 다른 사람이 만들었던 내용을 저장해야한다는 점


때문 입니다.


이런 내용들은 추후에 여러분에게 어떠한 것으로든 지적 재산이 될 수 있습니다.



3. 스케줄을 만들자


마지막으로 강조할 내용은 스케줄입니다.


Q. 왜 스케줄을 만들어야할까요?


A. 가장 큰 이유는 팀원들 스스로에게 책임감을 부여하기 위함 입니다.



시간 제한이 있다는 점은 항상 맡은 이에게 언제까지 끝내야 한다라는 책임을 느끼게합니다.


그리고 압박감을 느끼게 되지요. 물론 시간적으로 여유가 있다면 압박감은 덜하겠지만


언제까지 만들어야 한다는 점은 바뀌지 않습니다.



때문에, 팀 프로젝트를 진행 할 때는 꼭 스케줄을 만들어서 언제까지 무엇을 만들겠다 라는 규칙을 정해서 진행해야합니다.



적다보니 주관적인 내용들이 들어가면서 조금 글이 길어진 것 같습니다.


그래도 여기까지 읽어주셨다면 정말 감사드리고, 한줄 요약으로 마치겠습니다.



한줄 요약

 - 주 단위로, 작은 목표를 정해서 진행하고, 스케줄을 잘 관리하자!

posted by REDFORCE 2017. 4. 26. 22:04

3. ㅁㅁ을 자주 가져라.


팀 프로젝트를 어떻게 진행해야하는가? 하는 문제를


'보상', '참여 유도' 를 통해 이전 글에서 이야기 했었는데요.



세 번째로 언급할 사항은 "만남을 제때 가져라" 입니다.



응?? 왜 결론을 먼저 바로 얘기해주냐구요?


(숨겨봤자...뻔히 보이기 때문에...)



이미 첫번째 글에서 언급 된 


'3. 정기적인 회의 여부' 라는 항목에서 추론할 수 있기 때문에 결론을 바로 언급했습니다.



이 사항은 온라인/오프라인 작업에서도 똑같이 중요한 대목입니다.


정기 회의가 있는 회사라면 기본적인 내용이라 별로 유심히 보시지 않을 수도 있는데요.


혹, 대학 생활을 하시고 계시거나 별도의 온라인 활동을 통한 팀 프로젝트를 진행하고 계신 분들이 있으시다면 도움이 되실 수 있을까 해서 설명해보도록 하겠습니다.



앞서, 팀 프로젝트가 파토가 나는 경우의 절반은 팀원 참여의 부재로 인해 발생하는 예가 많다고 얘기한 적이 있습니다.


왜 그럴까요? 그냥 팀원 한명 자체가 삐꾸- 라서?



뭐...그렇다면 애시당초 사람 문제니 여기서 다룰 내용은 아닙니다.



그러나..참여를 하다가 중간에 파토가 나는 경우라면?


여러 요인이 있을 수 있으나, 여기서 다루고자 하는 것은 "팀 프로젝트가 잘 되다 파토가 나는가?" 라는 문제를 수면위로 끌어올리고자 합니다.


우리나라 IT기업들을 보면 흔히 회의를 엄청나게 많이하는 것을 볼 수 있습니다.

(아주 사람 귀찮게 하네 라고 느껴질 정도?)


또는 엄청 적게 하는 경우도 있지요.

(이건 뭐 하자는 건지 말자는건지...?)


잠시 '회의' 라는 말의 사전적 의미를 적어보겠습니다.


회의1, 回議
회의/훼이/
명사
  1. 주관자가 기안한 것을 관계자에게 돌려 의견을 묻거나 동의를 구하는 일.
회의2, 懷疑
회의/훼이/
명사
  1. 1.
    어떤 일이 진정으로 올바르고 확실한지의 여부를 의심하는 일.
    "인생에 ∼를 느끼다"
회ː의1, 會意
회의/훼이/
명사
  1. 1.
    뜻을 깨달음.
  2. 2.
    육서(六書)의 하나. 둘 이상의 한자(漢字)를 합하여 새로 한 글자를 만들고, 그 뜻도 합성되어 이루어지는 것. `日'과 `月'이 합하여 `明'이 되는 따위.
회ː의2, 會議
회의/훼이/
명사
  1. 1.
    여럿이 모여 의논하는 것.
    "가족 ∼"
  2. 2.
    어떤 사항을 평의하는 기관.
    "법관(法官) ∼"





뭔가 '회의' 라는 단어 자체에도 많은 뜻이 내포되어 있군요.



여기서 다루고자 하는 회의는 가장 첫번째 회의(回議) 와 가장 마지막 회의(會議) 입니다.


왜 제가 "만남을 제때 가져라" 라고 했을까요?



먼저 제가 여기서 언급하는 회의가 필요한 이유는 3가지로 정리 됩니다.

(일반적인 회의의 이유에 대해서는 언급하지 않겠습니다. 당연히 필요하니까 회의하잖아= _=)


1. 팀 프로젝트의 진행(Progress)를 확인하기 위해


2. 팀원들의 책임감을 고양시키기 위해


3. 팀 프로젝트의 개발 효율성을 증대시키기 위해



이렇게 3가지 이유 입니다.


왜 이렇게 나왔는지 각 이유를 따라 적어보도록 하겠습니다.




1. 팀 프로젝트의 진행(Progress)를 확인하기 위해


왜 팀 프로젝트의 진행도를 확인해야 할까요? 


음...그냥 관리차원에서? 서로 맡은 파트가 얼마나 진행 됐는지 감독하려고?


윗 사람이 아랫사람을 관리하는 것이라면 그럴지도 모르겠네요.


하지만 동일 선상의 관계를 가진 팀원들이라면 누가 누구를 관리/감독 할 일이 있을까요.

ㅁㅁ


제 대답은...


진행도를 확인하는 것은 모두가 다같이 책임져야하고 알아야하는 내용이기 때문이라는 것.


입니다.


(아마 2. 팀원들의 책임감을 고양시키기 위해. 라는 말이랑 겹쳐 보일 수도 있겠네요.

하지만 2번에서 언급할 근거는 다른 내용이니 걱정안하셔도 됩니다)



본론으로 들어가도록 하조~


흔히 IT기업에서 프로젝트 매니저 라고 하는 직군을 볼 수 있었을 겁니다.

이 사람들 대체 왜 있을까요? 저도 모르겠어요...


근데 뭔가 하는거 같긴해요..


위 말은 농담으로 적은 내용입니다만, 뭔가 필요하고 하는 일이 있으니까 있는 직군입니다.

(그 분들이 몸 담고 있는 직군의 정체성을 부인하고 싶은건 아니에..!)


(공격 하...지말..주..주세요..으어..)


그런데 소규모 팀 프로젝트 단위에서 프로젝트 매니저가 있을까요? 없겠지요~


하물며 회사도 아닌, 초급자/인디/동아리 등등...


이런곳에서 진행하는 팀 프로젝트라면? 더더욱 없습니다.


그래서 우리가 진행하는 팀 프로젝트가 어느 정도 진행되고 있고, 어디까지 왔는지를 서로서로가 확인할 필요가 있습니다.


그럼, 이렇게 해서 얻는 이점이 뭘까요?


바로 프로젝트 개발 계획의 조정이 가능하다는 점!

(개발 속도를 올린다 / 어떤 기능에 좀 더 주안을 두자. 등등)


더욱이 권위있는 리더가 이런 것들을 관리해주는 것이 아닌 팀 프로젝트라면 회의에서 즉석으로 얘기가 가능하기 때문에 회의의 필요성을 자주 느껴지실 겁니다.


물론 몇몇 분들은 회의 시간 자체도 아까워...라고 생각하실 수도 있으실텐데요.


다른 파트의 사람들과의 시간이나 협업 관계를 맺다보면 아마 저절로 필요성을 느끼실 수 있으

리라 생각듭니다.



그렇다고 너무 귀찮을 정도로 많은 회의는 가끔 짜증나긴하지요..




2. 팀원들의 책임감을 고양시키기 위해


회의를 한다는 것이 어째서 팀원들의 책임감을 고양시키는 게 될까요?


사실...책임감을 고양시킨다기 보다는 현실적으로 얘기하자면


회의에 참여해서 보여주기 위해 팀 프로젝트에서 맡은 부분을 반 강제적으로라도 참여하게 된다는 것 때문에 그렇습니다.



저는 자주 팀 프로젝트를 진행하는 사람들이 어떻게 진행해야할지 모르겠어...


라고 이야기하면 딱 한마디만 합니다.


"맨날 모여서 회의해 = _=)..그럼 뭔가 될꺼야"


(속으로)그리고 도주하는 너의 팀원을 보겠지...



회의라는 것은 어찌보면 사람을 귀찮게 하지만, 돌려 말하면 귀찮아지게 한다는 것은 뭔가 준비를 하게 만들기 때문에 귀찮게 한다는 것 입니다.


만약 회의가 귀찮지 않다면, 그건 회의를 좀 덜해보신듯...?은 아니고


이미 "즐기는 자"의 반열에 들어가신 것 일수도 있겠군요.



아무튼. 회의를 정기적/지속적으로 하면 각 팀원들의 참여를 유도할 수 있고, 회의에서 할 내용을 준비하게 만듬으로 팀 프로젝트를 지속 유지/개발 할 수 있습니다.


그래서 두 번째 이유를 팀원들의 책임감을 고양시키기 위해 라고 언급을 하였습니다.


 

3. 팀 프로젝트의 개발 효율성을 증대시키기 위해


음..회의 라는 건 사실 양날의 검 입니다.


작업할 시간에 영향을 끼칠 정도로 너무 많으면 오히려 방해 요소이고, 스트레스만 줄 수 있습니다.


그렇다고 너무 회의를 줄이게 되면, 현자 모드가 와버리는 경우가 있지요.



그래서 적당한 타이밍과 적당한 회의 시간이 중요합니다.


만약 같은 파트의 사람들끼리 모여있는 거라면 시간 제한 또는 스케줄을 만드는것이 좋습니다.


타임리미트 또는 due date(마감일)를 잡는다는 것은 현업에서도 흔히 발생하는 사건이며

일반적으로 그렇게 흘러갑니다.


개개인의 역량 및 스킬을 쌓기 위해 어떤 제한된 환경으로 국한 시키고 작업하는 습관은 나쁘지 않다 생각합니다.

(제 생각에는 개인 프로젝트에서도 적용시켜서 훈련할 필요가 있다 봅니다)


물론 상업적으로 진행하는 금전적인 목적의 팀 프로젝트라면 위 내용을 꼭 지킬 필요는 없습니다. (실력 쌓는것 보다도 일단은 돈버는게 중요하니까...만약 회사라면 이야기가 조금 다릅니당!!)


그리고 팀 프로젝트를 진행하는데 있어서 스케줄은 각 팀원들의 반 강제적 참여를 유도하게 됩니다. 만약 타임리미트가 없는 일이 주어졌다면, 그게 언제 끝날지 알 수가 없기 때문에 마냥 그 팀원이 해결해주기만을 기다리고 있어야하지요. 


(이런 점은 제가 뭐 따로 언급하지 않아도 다들 몸소 느껴보셨거나 느껴보실거라 생각듭니다)


따라서, 이런 스케줄이나 타임리미트들은 회의에서 정해지고 회의에서 결과가 다뤄지기 때문에 세 번째 이유로 언급하였습니다.




그럼 마지막으로.


대체 언제? 어떻게? 얼마나 길게? 자주? 회의를 해야할까요?


이 문제는 어떤 스타일이냐에 따라 개개인마다 그리고 팀마다 다르겠지만.



개인적으로는 주 1회 (2시간 동안)이 마지노선이라 생각합니다.


만약 일주일 동안 진척된 내용이 많지 않아서 회의할 내용이 마땅히 없더라도


위 이유중 1, 2번의 이유에 근거하여 회의를 진행할 필요가 있다고 보고 있습니다.




한줄 요약.

 - 정기적으로 회의를 진행해서 서로 무언가를 하고있고 진척되고 있어! 라는 걸 확인합시다.

posted by REDFORCE 2017. 4. 26. 20:38

2. ㅁㅁ를 유도하라.



일반적으로 팀 프로젝트는 서로 얼굴을 알고 있는 사람들끼리 진행 되는 경우.


오프라인으로 프로젝트가 진행되어, 서로 가까운 자리에서 진행되는 작업이


매우 능률이 좋고 작업 속도가 온라인에 비해 잘나오는게 사실입니다.



그런데...위와 같은 경우는 회사를 제외하고선 한 자리에 모여서 진행하기 어렵다는게 안타까운 현실입니다.


마땅한 사무실이나 작업실이 있지 않는 한, 공동 작업을 펼치기 어렵기 때문이조.


해서 결과적으로 "조별과제" 라고 하는 패러디 같은 것이 우르르 나오고


한 명이 개고생을 한다? 라는 상황들이 자주 연출되거나 팀 프로젝트가 파토나는 경우가 허다합니다.



그럼 팀 프로젝트는 무조건 오프라인으로 진행해야 되는가?


만약 그럴 수 있다면 정말 좋지만!! 현실이 그렇게 허락하지 않으니 문제입니다.


그리고 한 자리에서 같이 작업하는 것을 기피하는 사람들도 있을 수 있습니다.

(저 또한, 개인적으로 혼자 작업하는 것을 좋아하는 스타일)


이런 작업 스타일은 서로 존중해줘야 하며 그렇지 않는다면 

팀 프로젝트에 참여하고자 하는 동기가 깨질 수 있습니다.



만약 여러분이 


"온라인/오프라인 진행이 그럼 무슨 상관이냐. 그냥 팀 프로젝트 잘 진행하기만 하면 되지."


라고 결과만을 쫓아간다면, 

팀 프로젝트가 파토나거나 자신이 버스기사로 운전을 하고 있는 경험을 하게 될 것 입니다.




사실 위 생각대로 온라인/오프라인 진행은 중요하지 않습니다. 네. 그럼 왜 적었는가?


온라인/오프라인 작업이란 것은 이 글을 보시는 분들께 키워드를 던지기 위함입니다.



여기서 중요한 점은 온라인으로 작업을 같이하건, 오프라인으로 같이 작업을 하건.


중간 단계의 결과물을 도출하고 참여를 유도하라. 입니다.



사실 팀 프로젝트가 파토가 나는 경우의 절반은 팀원의 참여 부재로 인해 발생하는 사례가 많습니다. 글쓴이 본인도 많이 겪었고 글쓴이 본인도 그렇게 행동했던 적이 있어서 많이 반성하고 있습니다.



그럼..어떻게 참여를 유도할까요?




중요한 점은 내가 팀 프로젝트에 기여하고 있다 -> 참여에 따른 뿌듯함을 느낀다.


라는 것을 만들어야 합니다.



예를 들어서, 개발자들끼리 팀 프로젝트를 진행 할 때.


나의 코드가 다른 사람에게 어떤 기능을 제공해주거나 다른 사람이 내 코드를 통해 어떤 편리함을 제공 받았다면, 내 작업물이 도움이 되는지 피드백을 받는 것도 좋은 방법 입니다.



그러나 꼭 같은 분야의 사람끼리 팀 프로젝트를 진행하란 법은 없지요.



그럼 다른 파트의 사람들끼리 있을 땐 어떻게 해야 하는가?


가장 좋은 방법은 내가 당신을 통해 일하고 있어요~ 라는 점을 보여지게 하면 됩니다.



가령, 프로그래머 ↔ 디자이너 관계에서


디자이너가 캐릭터를 그리면 그것을 움직이게 만들어 주는 것이 개발자의 몫 입니다.


캐릭터가 만약 움직이게 된다면 디자이너는 자신이 그린 캐릭터가 움직이는 데에서 뿌듯함을 느낄 것이고, 프로그래머 또한 거기서 뿌듯함을 느끼겠지요.



이처럼 팀 프로젝트의 중간 개발단계의 결과물들을 통한 기여에 따른 결과에 대한 성취감을 얻는 것이 중요합니다.


그러나...말처럼 이런 경우가 쉽게 나오지 않는 예도 있습니다.




글쓴이 본인이 겪었던 한 예를 들어보겠습니다.


두 프로그래머 친구가 같이 팀 프로젝트로 게임을 하나 개발하기로 했습니다.


여러가지 내용을 개발하던 중..


A 친구가 플레이어를 만들고 싶다고 했습니다.


그러나 B 친구도 플레이어를 만들고 싶었습니다.

그래서 두 친구는 서로 플레이어의 개발 내용을 서로 나누기로 결정합니다.


A친구가 플레이어의 스테이트를 만들기로 하고

B친구가 플레이어의 액션과 인벤토리를 만들기로 결정했습니다.


A, B 두 친구가 만든 플레이어는 어떻게 됐을까요?



개판입니다. 


말 그대로 개판이에요. 난리가 아닙니다. 


플레이어 캐릭터에서 어떤 버그가 발생해서 B친구에게 고쳐달라고 했더니 이건 A 친구가 만든 거라 내가 못건들어. 라고합니다.


.....(뭐 어쩌라고...)



솔직히 어떤 거대한 프로젝트라면 큰 틀에서 내용을 나눠 역할에 따라 분담하는 것이 맞지만 너무 디테일하게 들어가서 어떤 역할과 의미를 가진 객체를 쪼개버리면 추후에 위와 같은 문제가 발생 하는 경우가 있습니다.


이런 경우 팀 프로젝트의 진행 자체에 자원적으로 많은 영향을 끼치게 됩니다.

(시간, 돈, 기분, 관계 등등...)



위 내용에 대해서는 추후 기회가 된다면 다시 언급하도록 하고...


다시 본론으로 돌아오겠습니다.



제가 위 사례에서 말하고 싶은 것은. 성취감을 얻을 수 있는 항목을 너무 분할하지 말아 달라는 뜻 입니다.


팀 프로젝트의 참여를 유도하기 위해 서로의 피드백이나 결과를 통해 기여에 따른 성취도를 얻는 것은 중요하다 말했습니다. 그러나 위 사례처럼 그 성취감을 얻을 수 있는 내용을 다른 사람과 나눠 버리게 되면 그 만큼 참여를 유도할 수 있는 능률 자체도 나뉘게 된다는 뜻 입니다.


그렇다고해서 나누지 말라는 뜻은 아닙니다.


어떤 거대한 프로젝트나 많은 기능을 가진 객체를 분담하여 개발하는 것은 좋은 방법이조.


다만, 프로젝트 스케일이 어떤가에 따라서 팀 프로젝트 참여를 유도함에 악영향을 끼칠 수 있다는 뜻 입니다.




마지막으로 정리하자면,


팀 프로젝트를 진행 할 때는 자신이 어떤 것을 맡고 있고,


맡은 분야에서 성취감을 얻을 수 있는지를 확인하시는 게 중요합니다.


(성취감을 얻을 수 있다? 라는 걸 매번 미리 알 순 없겠지만, 그것을 얻을 수 있을거야~ 라는 기대를 갖는 것 만으로도 충분합니다)


한줄 요약.

 - 팀 프로젝트에 자신이 기여하고 있고 성취감을 얻기 위해 지속적으로 참여하도록 유도하라.

posted by REDFORCE 2017. 4. 26. 18:57

많은 분들이 팀 프로젝트를 진행하다가 좌절하거나 파토나는 경험을 많이 하실텐데요.



글쓴이 본인도 수 많은 팀 프로젝트 경험을 쌓은 것은 아니지만


여러 프로젝트를 진행하며 겪었던 경험을 바탕으로


이런 관점으로 팀 프로젝트를 진행하는 것은 어떤가? 라는 제시를 하고자 적어보게 되었습니다.



먼저 어떻게 팀 프로젝트를 진행해야 하는가 고민하기 전에!



자신의 팀 프로젝트가 어떤 속성을 갖고 있는지 먼저 파악해야합니다.


프로젝트의 목적동기의도에 따라 팀 프로젝트를 진행하는 방향과 방식이 매우 달라집니다.


위의 3가지(목적/동기/의도) 항목에 따라 팀 프로젝트의 성향을 분류해보면 다음과 같은 요소들이 팀 프로젝트의 성향 및 방향을 결정하게 됩니다.


1. 상업적 / 비상업적

2. 온라인 작업 / 오프라인 작업

3. 정기적인 회의 여부

4. 개발 기간의 제한

5. 리더의 존재 여부


위 5가지 내용이 팀 프로젝트의 성향과 방향을 구분 짓는 주 요인입니다.


그 외 다양한 요인으로 인해 팀 프로젝트의 성향에 영향을 끼칠 수 있으나, 개인적으로 위 내용이 지대한 영향을 끼치는 항목들이라 생각하고, 아마 다들 같은 생각을 하시리라 믿습니다.


그럼 팀 프로젝트를 어떻게 진행해야하는가? 를 살펴보겠습니다.



1. ㅁㅁ을 확인하자.


팀 프로젝트를 진행함에 있어서 상업적인가 비상업적인가 하는 목적이 팀 프로젝트에서 가장 우선시 되는 중요한 요인입니다.


딱히 위 말의 의도가 비상업적인 것은 뭐가 다르나? 라는 뜻은 절대 아닙니다.


그저, 상업적인 목적의 프로젝트는 팀 프로젝트 참여도에 많은 영향을 끼치기 때문에 이 글에서 우선순위가 높게 잡혀있습니다.


이미 여러분은 일상에서 "조별과제" 라는 키워드의 패러디가 많이 나와있던 것을 많이 보셨을텐데요. 이 문제는 직·간접적으로 금전적인 것에 문제와 연관됩니다.


만약 어떤 금전적인 이익이 있거나 금전적인 것을 목표로 한다면

참여도와 개개인의 책임감이 높은것이 사실이고, 반대의 경우 참여도와 책임감을 고양시키기 어려운 게 현실입니다.


상업적인 프로젝트는 금전을 통해 프로젝트를 활발히 참여 시킬 수 있지만

비상업적인 프로젝트는 대체 어떻게 해야할까요?


원초적으로 상업적이고 금전적인 목표가 아니기 때문에 해결할 방안이 없을까요?



이 질문에 대한 답을 먼저 해드리자면


해결 방안이 없는 것은 아닙니다.

그럼 어떻게??


한번 사고를 전환해서 생각해보겠습니다.


비상업적인 팀 프로젝트의 경우. 그 목적이 상업화가 아닌 다른데에 있다는 것을 주안점으로 둬야합니다.


예를 들면, 난 이 프로젝트를 포트폴리오로 쓰겠어! 라든가.


난 이 프로젝트를 진행하면서 여러 사람들과 사귀고 싶어! 라든지..


금전적인 것이 아니더라도 다른 목표는 많이 나올 수 있습니다.

그리고 이 목표는 개개인마다 다를 수 있지요.



결과적으로 이 말에 대한 의미를 풀어보면 


1. 상업적 / 비상업적 -> 내가 얻을 수 있는 보상은 무엇인가?


라는 문제로 직결됩니다.



이 보상이라는 부분이 나의 목표와 부합하고 만족스러운 결과를 낼 수 있다면

참여도와 책임감을 올릴 수 있고, 그렇지 않다면 좋은 결과를 내기 어렵습니다.


따라서, 먼저 팀 프로젝트를 진행하기전에 


개개인이 원하는 보상을 팀 프로젝트를 통해 얻을 수 있는지를 먼저 확실히 확인해야 합니다.


반대로 팀 프로젝트의 관리자 또는 리더의 입장이라면 팀원들에게 위 보상을 적절히 챙겨줄 수 있는지를 꼭 확인해야 합니다.



결과로 따라올 보상이 팀 프로젝트를 진행함에 있어 모두에게 적절하다면


그 프로젝트는 어떤식으로든 모두 보상을 위해 참여하게 될 것 입니다.




한 줄 요약. 

 - 팀 프로젝트에서 얻을 수 있는 보상을 확인하자.

posted by REDFORCE 2017. 4. 21. 20:39

#1. Engine System

 + WinMain - EngineSystem

 + EngineCore

 + EngineError

 + MainNode


#2. FrameWork

 + Grahpics

 + Image - SpriteData

 + Layer  (현재 글)

 + Input

 + Game

 + Manager

 + Game Interface

 + Utility


#3. Testing Module

 + 2D Image Test

 + 2D Animation Test

 + Game UI Test


-----------------------------------------------------------------------


LayerManager Class .cpp 내용을 살펴보도록 하겠습니다.



1. 간단히 생성자와 소멸자 그리고 initialize 함수를 보도록 하겠습니다.



생성자 부분에서는 현재 LayerState 값이 LAYER_NONE 값으로 초기화 됩니다.

소멸자는 release 함수 호출뿐이군요.


initialize 함수에서는 미리 네임스페이스로 만들어두었던 기본 LAYER들 값들에 맞춰서

addLayer 함수를 호출하여 레이어를 등록하도록 되어있습니다.


반복문으로 처리하면 안되~? 라는 생각도 해봤습니다만


= _=아마 당시에 만들면서 귀찮아 그냥 몇개 안되니까 하드코딩으로 만들자

라고 생각했던 것 같네요.


enum Class 타입의 값을 반복문으로 알아서 처리되게끔 고치실 수 있다면 initialize 코드를 개선해보시는것도 좋을 것 같습니다.



release 함수에서는 각각 Layer들이 new 로 할당되어 등록되었기 때문에


해지해주는 과정이 이루어지고 있습니다.

(SAFE_DELETE 매크로를 이용하여 해지합니다. SAFE_DELETE 매크로는 graphics 글에서 언급했습니다.)



initialize 함수의 addLayer 과정을 통해 다음 그림과 같이 Layer가 layerVec에 쌓이게 됩니다.


레이어 순서는 번호 순서대로 위에서 아래로 렌더링 순서가 정해집니다.

enum class 형태의 값 순서대로 읽어 가기 때문인데요. 


여기서 중요한 점은 AddLayer 함수를 호출하면 레이어가 enum Class 값 형식에 맞춰서 정렬됩니다.


만약 같은 Layer 타입이라면 딱히 같은 타입들사이에서는 정렬 될 필요가 없다 느꼈기 때문에


다른 타입들간의 순서만 정렬시켜줍니다.



그럼 이제 AddLayer 함수를 살펴보겠습니다.


2. addLayer


addPlayer 함수는 initialize() 에서 Layer를 등록하면서 호출 되었덩 함수입니다.


코드를 먼저 보겠습니다.



// 레이어 등록이 성공적으로 끝났다면 true값으로 바뀝니다.

Line 3 : bool success = false;   


// 만약 레이어 타입이 네임스페이스LayerManagerNS::none 과 같다면 false를 리턴합니다.

Line 6 : if (layerkey.compare (LayerManagerNS::none) == 0) 


Line 10 ~ 15 : 현재 레이어 리스트에 등록된 같은 레이어가 있는지 확인하여 있다면 false를 리턴합니다.


Line 17 : 여기까지 왔는데 아무이상없었으면 Layer를 등록합니다. 


Line 18 : success 값을 true 로 변경합니다.


Line 20 : 레이어 정렬 함수를 호출합니다.



아마 위에 적어둔 설명을 보시면 아마 AddLayer 함수 내용자체는 별로 어려운 것이 없을 것 입니다.


★주의 할 점은 현재 layerList 라고 하는 MAP 형태의 컨테이너에만 

Layer를 담았다는 것을 꼭 확인하시기 바랍니다.



3. deleteLayer


DeleteLayer() 함수는 AddLayer 함수와 반대로 등록 된 레이어를 삭제하는 함수입니다.



간단히 layerList 에 등록 된 레이어 중에 파라미터로 받은 레이어 이름과 비교하여

등로 된 레이어가 있다면 layerList에서 해당 항목의 레이어를 erase 시킨 후

sortLayer() 함수를 호출하여 줍니다.



4. sortLayer


네 번째로, addLayer과 deleteLayer에서 호출한 sortLayer 함수를 살펴보겠습니다.


sortLayer는 함수명 그대로 레이어들을 정렬시키는 함수입니다.




위에서 주의할 점으로 layerList 라고 하는 Map 타입의 컨테이너에 Layer를 담았었다는 것을 보셨을 겁니다.


그 이유는 바로 layerList (Map 컨테이너)에서 정렬을 수행 한 후

진짜 컨테이너인 layerVec (Vector 타입의 컨테이너) 에 정렬 시킨 후 담아두기 위함입니다.


sortLayer( ) 함수 자체는 간단하게 3줄로 되어있습니다.


1. std::vector<std::pair<std::string, Layer*>> 형태의 벡터 컨테이너를 먼저 만듭니다.

그리고 생성과 동시에 layerList에 담겨있는 Layer들을 그대로 begin 부터 end까지 넣어줍니다.


2. 미리 헤더에 생성해둔 Sort 템플릿을 이용하여 정렬시킵니다.


3. layerVec 의 값을 위에서 정렬 시킨 컨테이너로 넣어줍니다.



그리고 SortLayer에서 중요한 점은 아래의 템플릿을 이해를 하셔야 합니다.




방법은 간단히 좌우 값을 비교하여 작은 값 순서대로 정렬을 시킵니다.


아마 정렬하는 로직은 간단해서 이해하시기 어려움이 없을 것이오나, 템플릿을 사용하는 점에대해서는 스스로 템플릿이 뭔지 알고보셔야 아마 이해하시는데 문제가 없을거라 보입니다.



'MyProject > SephyEngine' 카테고리의 다른 글

June_Engine #2_Input .h  (0) 2017.05.18
June_Engine #3_LayerManager Class .h  (0) 2017.04.21
June_Engine #3_Layer Class  (0) 2017.04.21
June_Engine #3_Image Class .cpp (2)  (0) 2017.04.20
June_Engine #3_Image Class .cpp (1)  (0) 2017.04.19
posted by REDFORCE 2017. 4. 21. 07:18

#1. Engine System

 + WinMain - EngineSystem

 + EngineCore

 + EngineError

 + MainNode


#2. FrameWork

 + Grahpics

 + Image - SpriteData

 + Layer  (현재 글)

 + Input

 + Game

 + Manager

 + Game Interface

 + Utility


#3. Testing Module

 + 2D Image Test

 + 2D Animation Test

 + Game UI Test


-----------------------------------------------------------------------



이어서 LayerManager Class에 대해서 설명하도록 하겠습니다.



Layer Class를 보셨다면 헤더 파일 내용 중에

enum class 타입으로 선언되어있는 Layer 리스트를 보셨을 겁니다.


위 그림은 해당 리스트 내용을 그대로 순서대로 나열한 것 입니다.



다시 뒤로 돌아가서 코드 보기 귀찮으신 분들을 위해 enum Class만 다시 올려드립니다.



보는 바와 같이 LAYER_NONE 부터 LAYER_LAST 까지.


 (1) LAYER_NONE : 초기화용 레이어 타입

 (2) LAYER_FIRST : 첫 번째 레이어

 (3) LAYER_BACKGROUND : 배경 레이어

 (4) LAYER_DEFAULT : 일반 레이어

 (5) LAYER_UI : UI 용 레이어

 (6) LAYER_LAST : 마지막 레이어


순으로 총 6가지의 레이어 타입이 있습니다.


만약 무엇보다 우선순위를 높여서 출력하고 싶으신 것이 있다면 첫 번째 레이어로 이미지 클래스에서 타입을 결정시키면 되고.


일반적인 이미지 출력(캐릭터, 아이템, 애니메이션 등)은 LAYER_DEFAULT 를 이용하시면 됩니다.

그 외에 레이어들은 다른 레이어와 똑같이 직관적이므로 설명은 생략하겠습니다.


만약 어떤 설정을 안한다면 모든 이미지들은 LAYER_DEFAULT 값으로 들어갑니다.



그럼 Layer에 대한 복습이 다시 됐으리라 생각하고, 

LayerManager를 바로 살펴보도록 하겠습니다.


Layer Manager 헤더 내용입니다.



1. LayerManagerNS


먼저 namespace 를 살펴보시면 const std::string 타입으로 미리 구성 된 LAYER의 이름들이 들어가있습니다.



2. 변수들


그리고 private: 에 선언되어있는 변수를 확인해주시기 바랍니다.


 (1) std::map<std::string, layer*> layerList;  (레이어 정렬 전 MAP 컨테이너)

 (2) std::vector<std::pair<std::string, layer*>> layerVec; (레이어 정렬 된 VECTOR 컨테이너)

 (3) enLayerList curLayerState; (현재 렌더링 해야할 레이어)


이렇게 3가지의 변수가 있습니다.



3. 함수들


다음  public: 에 여러가지 함수들이 있습니다만...

역시나 getter/setter함수들이 주로 있을 뿐, 현재 눈여겨 봐야 될 함수는 SortLayer( ) 밖에 없습니다.



4. 정렬용 템플릿


네 번째로 확인할 점은 레이어들을 정렬 시키기 위해 만들어 둔 템플릿 입니다.

std::less를 이용하여 받아온 매개변수를 left / right 비교를 통해 true/false를 뱉어줍니다.




헤더에서 일단 살펴볼 내용들은 위에 언급한 정도이고,

자세한 설명은 .cpp에서 이어가도록 하겠습니다.

'MyProject > SephyEngine' 카테고리의 다른 글

June_Engine #2_Input .h  (0) 2017.05.18
June_Engine #3_LayerManager Class .cpp  (0) 2017.04.21
June_Engine #3_Layer Class  (0) 2017.04.21
June_Engine #3_Image Class .cpp (2)  (0) 2017.04.20
June_Engine #3_Image Class .cpp (1)  (0) 2017.04.19