졸면서 꿈을 꿨는데, 꿈속에서 We Rule을 만드는 꿈을 꾸었다.
나름 Direct3D로 개발했는데 다행히도 Visual Studio로 작업을 했었다.
만약 꿈속에서까지 맥킨토시에 XCode가 나왔다면 그건 정말 악몽이었을꺼다.
지금도 꿈 내용이 뚜렷히 기억나는 것은 아마 누군가의 인셉션 때문인지도 모르겠다. ㅋ
인셉션 해준 수고 때문에 꿈 속 이야기를 해볼까 한다.
우선 (꿈 속) 프로젝트의 시작은, 다른 팀의 부탁이었다.
We Rule같은 게임을 만들어야 하는데 만들 사람이 없다, 니가 좀 도와주랴. 그렇게 시작된 (꿈 속)프로젝트였는데 아마 최근에 있은 어떤 서버 프로젝트 사건의 영향이 아닐까 싶다.
어떤 서버 프로젝트 사건이란?
자, 그럼 (꿈 속에서)We Rule을 어떻게 만들었는지 살펴보기로 하자.
NPC 돌아다니는 것과 다른 플레이어의 성을 방문하는 것도 재미있는 이야기꺼리지만
(꿈 속에서) 만들지 않았기 때문에 적지는 않겠다.
언젠가 실전 프로젝트 형식으로 적어볼까 하는데 그때는 블로그는 아니고 아마 마소같은 잡지가 되지 않을까 한다.
1) 요구사항 분석
We Rule은 대표적인 아이폰용 SNG게임으로 농사를 지어 건물을 세우고 농사와 건물에서 돈을 버는 게임이다. 물론 돈을 주고 땅을 더 사서 땅을 넓히거나 동서남북의 앞마당 멀티를 뛸수도 있다. 따라서 가장 기본은 지형 배열 크기에서 시작했다.
핵심이 되는 농장와 건물은 그 성격이 비슷하다. 정해진 가로 x 세로 너비를 가지며 일정 시간이 지나면 돈을 생산한다. 플레이어가 클릭하지 않으면 회수될수도 있다. 농장과 건물은 일정 시간이 되면 항상 회수되며 건물은 광산이 회수된다. 건물이나 농장이 하나 지어지면 거기에 맞는 NPC가 필드를 돌아다니지만 앞서 말했듯 (꿈 속에서는) NPC는 구현할 필요가 없었다니까 NPC는 논외로 하자.
2) 클래스 설계
요구 사항 분석에 따라서 농장과 건물은 같은 Object에서 파생된다고 할수 있다. 왜 굳히 이 둘을 상속받는지는 예전 포스트(http://rhea.pe.kr/242)를 참조하자. 또한 농장과 건물은 둘다 같은 건설 메뉴(?)에 등장한다. 성격이 좀 달라도 이 둘을 함께 관리하기 위해서는 공통된 클래스에서 상속받을 필요가 있다.
class CGameObject
{
public:
virtual wstring GetName() = 0;
virtual CGameTime GetCompleteTime() = 0;
virtual CGameRect GetRange() = 0;
virtual long GetPrice() = 0;
virtual bool GetIsSettingEnable() = 0;
// ....
};
꿈에서 깬 지금이라면 당연히 Protype 패턴을 활용해 다양한 건물들을 생성하는게 정답인 것 같다. 건물의 자료형이 같으므로 Abstract Factory, 혹은 Builder 패턴은 어울리지 않는 듯 하다.
Protype을 위해 클래스를 살짝 변경하면 다음과 같다.
class CBuilding : public CGameObject
{
public:
wstring GetName() { return _T(""); }
CGameTime GetCompleteTime() { return gameTime; }
CGameRect GetRange() { return gameRect; }
long GetPrice() { return 0L; }
bool GetIsSettingEnable() { return true; }
virtual CBuilding* Clone() = 0;
private:
CGameTime gameTime;
CGameRect gameRect;
};
class CDragonsLair : public CBuilding
{
public:
CBuilding* Clone() { return new CDragonsLair(*this); }
// 오버라이딩 구현
};
class CBuildingComposite : public CBuilding
{
// 더 이상 자세한 설명은 생략한다.
};
굳히 건물마다 클래스를 만들어야 하는지 의견이 갈릴수도 있는데 머 선택이야 개발자 마음대로다. 그래도 이 방식을 더 추천하는 것은, 각 클래스를 DLL로 빼서 외부 파일을 이용한 Plug-In형식으로도 사용할수 있기 때문이다.
하지만 항상 말하듯, 게임 플레이어에게는 전혀 중요하지 않은 내용이므로 업데이트 잘하는 방향으로 알아서 구현하면 될 것이다.
3) 이벤트와 프로토콜
클래스는 대강 이렇게 마쳤지만, We Rule에서 가장 중요한 속성으로 돈을 만들어내는 시간이 있다. 여기서 실제적인 설계가 가장 크게 갈리게 된다.
해킹을 막는 가장 좋은 방법이다. 그러나 엄청난 서버 연산이 들어가며 객체가 늘어날때마다 쓰레드는 추가된다. 사용자 증가에 따라 서버 비용을 막지 못할 것이다. 또한 재배시간이 완료되면 서버는 클라이언트에게 Send()를 해서 재배가 되었다고 알려줘야 한다.
2) 클라이언트에서 관리한다.
서버는 재배 시작 시간만을 알고 있다. 클라이언트에서 요청하면 재배 시작 시간을 알려주고 클라이언트가 객체에 속성(재배 완료 시간)을 비교한다. 클라이언트는 타이머를 계속 돌리며 해당 시간이 되면 재배를 하라는 이미지를 내보낸다. 요청의 싯점은 해당 필드가 보여질때이다.
(꿈 속에서는)이중 2번째 방법을 선택했다. 이는 We Rule이 HTTP 프로토콜로 작동되는 게임이라 예상되기 때문이며(그 증거로 서버와 Connection이 끊겼다고 메시지가 와도 다시 클릭하면 정상적인 작동이 되기 때문인데 가장 쉬운 방법은 HTTP를 쓰는 것이다. 패킷 분석을 해보면 금방 알겠지만...) 아이폰 3GS보다 아이팟 2.5세대에서 훨씬 더 쾌적하게 진행되는 것으로 보아 클라이언트 계산이 확실하다고 판단했기 때문이다.
암튼 We Rule과 God Finger, We Farm의 프로토콜은 조만간 분석해볼까 한다. 솔직히 전부터 할려고 몇번이나 시도했지만, 집 PC와 테스트를 위한 장비가 서로 잘 맞지 않은 문제가 있어 여러번 실패했었다.
마지막으로 (꿈 속에서는)3D 타일맵에 객체들도 전부 3D였지만 그래픽 이야기를 굳히 할 필요는 없을 것 같다.
스마트폰과 SNG들이 급부상하며 이전에는 게임에서 메인으로는 사용하지 않던 HTTP가 SNG에서 많이 사용되고 있는데 10여년전부터 이와 같은 모델을 생각해왔기에 이러한 꿈을 꾼게 아닐까 싶기도 하다. 어쩌면 정말 인셉션이든지.
말나온 김에 다음 포스트에는,
언급한 세가지 SNG들의 패킷을 분석해볼까 다짐한다. <-- 이것이야말로 인셉션 당한 증거!
