이 글은 KGDC2002용으로 씰 패키지 게임의 프로그래머이신 김병철님이 쓰신 것을 허락을 받아 올려놓은 것입니다. 글에 쓰인 이미지들은 글의 이해에 도움이 될까 하고 제가 가지고 있는 씰의 이미지를 사용하였습니다.
다시 한번 글의 공개를 허락해주신 김병철님께 감사드립니다.
씰 패키지 사진
씰 포스트 모템 작성자 : 김 병 철
게임 데이터 :
게임데이터
● 개발자 : 총 10명 ● 외주용역 : 1명 ● 예산 : 모름 ● 개발기간 : 10개월 ● 발매일 : 2000년 4월 ● 개발플랫폼 : Win 9X
Seal은 가람과바람이라는 영세게임업체에서 개발한 게임으로 발매당시부터 별 뚜렷한 반응을 보이지는 못했지만, 일부 매니아층을 형성하게 만든 매우 이례적인 타이틀중 하나이다. 플레이 스타일은 대중적인 일본 RPG의 방법론을 그대로 답습하고 있다. 이것은 요즘 시대적 상황으로는 매우 고답적인 방법론을 취하고 있다고 할수 있다. 게임에 사용된 기술은 이미 일반적으로 사용되고 있는 알파블랜딩 일변도의 특수효과 기술과 조건분기를 이용한 스크립트등이 사용되었다.
Seal이 그나마 여타 다른게임과 차별화 되는 부분은 2D캐릭터의 애니메이션을 이용한다양한 연출과 그에따른 드라마틱한 상황연출, 그리고 다양한 조건분기에 의한 많은수의서브이벤트 일것이다.
Seal에 사용된 캐릭터 애니메이션은 일반적은 PC게임에서는 볼수 없을 정도로 꽤 많은양이 사용되었는데, 이정도의 애니메이션을 사용한 게임은 국내에서는 창세기전 시리즈정도밖에 없을 것이다.
조건분기에 의한 다양한 서브이벤트는 이미 국내에서 포가튼사가등의 일부게임에서 시도된 바가 있는 방식이다. 물론 포가튼사가는 서브이벤트 일변도의 게임진행방식을 취하는데 반해 Seal은 큰 메인스토리 맥락을 따라서 진행되면서 서브이벤트가 발생 또는 소멸되는 방식을 취하고 있다.
Seal은 가람과바람이 KDE내 게임개발팀에서부터 독립하면서 만들어진 첫 타이틀이자 마지막 타이틀이다. 처음 Seal이 기획되기전 이미 두개정도의 타이틀에 대한 기획과 시나리오작업을 하고있던 가람과바람은 시장성등을 판단하여 급거 세번째 기획안인 RPG로 방향을 선회한다. 4월에 시작된 세타이틀에 대한 기획작업은 7월이되어서야 끝나게 되고, 이시기에 프로젝트 진행자가 바뀌는 등의 일련의 고초를 겪게 되었다. 이에 Seal은 4월에 첫 기획을 시작하여 난항을 겪다가 8월에 이르러서야 제대로된 작업을 시작하게 된다.
Seal은 공식적인 기획문서는 존재하지 않는다.
자세한 데이터베이스는 존재하지 않지만, 대강 A4지 200장분량의 배경 러프가 그려졌으며, 이 배경러프의 초안은 A2사이즈의 달력종이 뒷면(이 종이는 아직도 팀내에 누가 보관하고 있다. 이것을 본 모 개발자는 가람과바람을 변태라 불렀다고 전해진다)에 그려졌다. Seal은 이 팀의 전작인 Leithian의 시스템을 답습하고 있다. 그러나, Leithian의 시스템의 모호함에 따라, 각각의 파라미터수치가 구체적이지 못하고 추상적으로 그려진데 대해 거꾸로 파라미터수치를 축소하고 구체적이고 직관적으로 바꾸도록 수정하였다.
인터페이스또한 Leithian의 비 직관적이고 복잡한 인터페이스를 대폭 수정하고, 최소한의 키배열을 이용한 직관적이고 단순한 게임 인터페이스를 가지도록 수정되었다. 레이디안에서도 사용되었던 조이스틱기능을 이어받아, 4버튼 조이스틱, 또는 게임패드만으로 모든 게임을 진행 할 수 있도록 배려하였는데, 이러한 방식은 당시 게임들이 마우스인터페이스를 대거 지원하는 방향과는 반대되는 선택이었다. PC게임보다는 Console 게임에 가까운인터페이스를 취하고 있다.
Seal의 게임내의 구조와 데이터구조는 레이디안에서 사용되었던 구조를 거의 그대로 활용하고 있다. 일부분 수정된 것은 스프라이트구조가 1차원 배열구조에서 2차원 배열로 바뀌어서 편집이 편해졌다는 부분과 전투부분이 독립적으로 변하면서 전투를 모듈화 시켰던부분을 제외하고는 크게 달라진 부분이 없다. 전투를 모듈화하였기 때문에, 전부맵을 새로이 수정할 수 있는 에디터가 추가되는 등 일부 에디터가 추가되었다. 기본적인 부분은이미 레이디안에서 대부분 검증된 코드를 사용하였다.
씰이 레이디안보다 완성도가 높은점은 대부분의 코드를 검증된 코드를 사용한 이유도 있겠지만, 실제 작업보다 기획 또는 구상작업이 먼저 선행되었고, 이것을 작업하는 중간에 크게 변경하지 않았기때문에, 레이디안보다 상대적으로 노가다 프로그래밍이 많은 마법들의 프로그래밍을 많은 시간을 두고 작업할 수 있었다는 데 있다. 또한, 전투부분을 제외하고는 이전에 사용했던 코드였기 때문에 디버깅작업등이 줄어들었고, 작업기간내내 대부분의 시간을 전투부분 프로그래밍에 할애할 수 있기때문이었다.
레이디안에는 스크립트엔진자체에 몇가지 큰 결함이 있었지만, 씰에 오면서 A.I를 수정하면서 이러한 문제가 해결되었고, 실제로 스크립트의 논리적 결함을 제외하고는 프로그래밍적인 버그는 거의 존재하지 않았다. 물론 다양한 하드웨어 테스트를 하지 못했기 때문에 몇몇 하드웨어에서 오류가 일어나는 호환성 부분은 약점으로 지적되기도 하였지만, 실제 판매량이 무척 미미하기 때문에, A/S문의시에도 호환성부분으로 문의를 받은 적은 별로 없었던 것으로 기억된다.
물론 스크립트의 양이 이전에 비해 워낙 방대하고 수십가지 조건이 난무하는 상황이 벌어졌기 때문에, 스크립트의 논리적 버그는 상당시간동안 버그 패치를 해야했던 점이 있다. 버그패치도 3회가량 행해졌고, 확장팩이란 이름으로 버그패치도 단행하였지만, 확장팩에서 마져도 확장팩 나름의 버그가 발견되어 확장팩의 버그패치(이름하여 버그패치의 패치 )가 단행되기도 하였다.
전투시스템에 대해서는 Leithian에서 사용된 액션방식을 탈피하고 고전적인 턴베이스로돌아가고 말았다. (일종의 퇴보라고 생각할 수 있다.) 여기에 턴베이스와 리얼타임을 합성하는 작업을 하게 되었다. 이 방법은 매우 많은 시행착오를 거치게 되었고, 전투프로그래밍은 실제로 게임전반에 걸쳐서 계속 수정되었고, 9월부터 출시전까지 전투프로그램은 계속 수정되기에 이른다.
전투시스템에 사용된 기술은 일반적인 턴베이스에 사용되는 기술과는 다른방식을 적용하였다. 턴베이스는 일반적으로 입력된 수치에 의해 결과값이 나오는 방식이다. 결과값은애니메이션으로 보여지며, 이 결과값은 프로그래밍한 패턴이상 나오지 않는 것이 보통이다.
Seal에서는 이방식보다 액션의 방식을 추구하였다. 입력된 수치에 의해 애니메이션이나 동작이 진행되지만, 이 동작중간 중간, 좌표 추적 및 상황판단에 의해 결과값이 변형되는 방식을 취한 것이다.
그러므로, 프로그래머가 의도하지 않은 매우 많은 패턴이 등장하게 되었다. 공격과 회피가 동시에 가능하다던가, 공격시 적과의 공중에서의 공격 캔슬등이 이때 등장하게 되었다. 정확하게 말하자면, 실제로 게임내의 모든 충돌 및 공격판정은 실시간으로 이루어진다.
실시간 충돌판정은 캐릭터들의 움직임시 공중 인카운터를 판정하는데 사용된다. 공격의 판정은 캐릭터내에 정확한 판정프레임정보를 삽입함으로써 판정프레임에 캐릭터가 정확히 해당 위치에 있는지를 검사한다. 이렇게 함으로써, 캐릭터가 자리에 없을 경우 공격이 실패하는 것이 가능하게 된다. 판정프레임정보를 삽입함으로써 얻는 또다른 효과는 타격시 맞는 쪽의 정확한 리액션 타이밍을 알 수 있다는 것이다. 즉, 캐릭터의 타격과 효과, 효과음, 맞는쪽의 반응이 정확히 일치할 때 타격감을 증대시킬 수 있다는 것인데, 판정프레임 정보를 이용하여 이러한 타격감을 확실히 증대시킬 수 있었다. (실제로 Seal은 턴베이스 게임으로써는 타격감이 좋은편에 속한다.) 위치판정은 아군끼리의 방어에도 사용된다. 방어를 하게될 경우 공격자와 타격자의 중간에 놓이게 되므로 타격자대신 방어를 하게되는 것이다. 실제로 따로 프로그래밍을 하지 않고, 위치판정만으로 판별이 가능해진다.
턴은 실시간으로 흘러가며, 일반적인 턴베이스 게임들이 명령을 입력하는 중에는 시간이 흘러가지 않도록 되어있는데 반해, Seal은 명령을 입력하는 중간에도 시간이 천천히 흘러서 명령을 내리다가 얻어맞을수도 있다. 이러한 점 때문에 결국은 전투는 여타 다른 턴베이스 전투를 채용한 게임에 비해 엄청나게 어려워진 것이다(역전홈런!).
씰의 구조를 잠시 살펴보자면, 전체적으로 크게 세가지 모듈로 나눠져있다.
첫 번째, 게임의 메인부분이다. 이곳에서는 주인공의 움직임과 동료들의 움직임, NPC의 움직임을 제어한다. 씰에서는 맵에 돌아다니는 몬스터들도 모둔 NPC로 취급하였다. NPC는 독자적인 스크립트를 가지고 있어서, NPC들과 충돌시 이벤트를 호출하는데, 몬스터들은 이때 전투스크립트를 호출하게 된다. 이 전투 스크립트는 강제 이벤트전투시에도 사용되게 된다.
두 번째 모듈은 전투모듈이다. 전투모듈은 전투를 처리하는 부분인데, 여기서는 몬스터의행동 패턴(턴베이스니만큼 많은 패턴이 존재할 것 같지만, 오히려 패턴의 조합이 적다.)을적용시키고, 몬스터나 주인공들의 마법과 효과를 표현해주었다. 씰은 전투시 강제 이벤트가 나오기 때문에, 이 전투모듈에도 스크립트루틴이 포함되어있다.
세 번째 모듈은 완전히 모듈로 분리되어있지는 않지만, 스크립트 모듈이다. 스크립트모듈은 메인이나 전투에 밀접한 관계를 가지기 때문에 완전 모듈화가 불가능하여, 전투모듈과 메인모듈 양쪽에 약간 다른모습으로 추가되어있다. 스크립트는 게임의 모든 현상을 자유로이 컨트롤 할 수 있도록 되어있으며, 실시간 스크립트로 입력제어권이 스크립트엔진에 할당된다는 것을 제외하고는 나머지는 유저가 인터페이스에 명령을 입력하는 것과 동일한 동작을 하도록 제작되어있다.
씰은 확장성을 위주로 제작된 레이디안의 엔진을 거의 그대로 이어받아 씰이라는 게임에 맞게 Modify한 것으로 프로그래밍 자체의 완성도와 안정성은 상당한 수준이고, 실제로 코딩의 안정성을 위해 출시 3개월전부터는 게임에 새로운 기능을 추가하지 않고 스크립트부분에 대한 수정만을 가하고 안정화을 하였다.
개발기간은 대략 10개월로 추산되는데, 이중간에 가람과바람은 Demo버젼 작업을 결심하게 된다. 시장성에 대한 확실한 판단이 미비한 상태에서 사용자의 반응과 미흡한점을 미리 취합하려는 포석이었다.
이 포석은 적중하였는지 적중하지 않았는지 잘 모르겠지만, 사용자들에게 많은 의견을 취합할 수 있었고. 2개월여간의 발매연기와 함께 게임을 버젼업 및 수정하기에 이른다. 또한 버젼업 된 부분은 추후에 데모버젼의 업그레이드형태로 다시 배포되었다.
데모버젼을 작업할때, 같이 작업을 하던 일러스트레이터가 개인적인 사정에 의해 일을 중단 하게 되자, 팀내에서 일러스트를 충당하게 되는 상황에 직면하게 된다.
자금적 압박에 시달리던 가람과바람은 결국 외주보다 팀내 해결이라는 고육책을 사용하게되었다. 하지만, 이 판단은 나중에 대중성이 부족한 일러스트라는 결과를 나타내게 되고, 판매량에 꽤 영향을 주었다는 후문이다.
데모버젼이후에 데모수정 그리고 마스터버젼까지는 대략 5개월여의 기간이 소모되었다. 매우복잡한 조건분기에 의해 다수의 스크립트 버그가 발생하기에 이르러, 베타테스트를 결정한다. 하지만, 베타테스트기간과 출시일의 기간이 짧을수 밖에 없는 상황에서 결국 베타테스터를 모집하지만, 사실상 알파테스트를 치루게 되고 만다. 이 상황을 곱씹어 본다면, 국내 게임시장의 영세성 어쩌구 하는 말이 나올법도 하지만, 베타테스트기간을 보름으로 잡고 베타테스터들과 씨름을 하며 버그작업을 하게 된다. 이 버그작업을 마치고, 무슨 시연회인지 뭔지를 치루고 난 후에 Seal은 발매하기에 이른다.
다만, Seal은 데이터의양이 매우작은 게임에 속하게 되어서인지, 발매 후 몇일 후에 Warez에 Rip버젼이 등장하게 된다. (무려 70메가 -.-) 그외에 여러가지 문제에 의해 Seal은 시장에서 참담한 실패를 겪게 된다. 마케팅이 결여된 타이틀 개발은 즉 실패와 연결된다는 교훈을 얻게 되기도 한 게임이다.
씰에서 부족한 점이라면, 저사양층까지를 섭렵하려다보니, 상대적으로 고사양유저들에게 고사양에 맞는 높은 그래픽 퀄리티와 화려한 효과를 보여주지 못한점이었다.
물론 8비트모드와 16비트모드가 존재하지만, 실제적으로 데이터포맷을 바꿔주는 것이 아니라, 동영상을 좀더 좋은 퀄리티로 출력하기 위해, 16비트모드를 선택한 것 일뿐, 실제 게임그래픽은 바뀌는 부분이 없다. 그렇기 때문에 씰은 그래픽적으로 그시대의 화려한 그래픽을 보여주지 못한 게임이었다. 물론 게임성으로 어느정도 커버한다고는 하지만, 요즘게임에서 어느하나 뒤떨어져서는 살아남기 힘들다는 점을 생각한다면, 전체적으로 게임자체의 완성도를 떨어뜨리는 결과를 가져왔다고 볼 수 있다.
디버깅을 위한 지침 :
※ 디버깅을 위한 몇가지 지침을 여기서 다시 한번 울궈먹기로 하겠다(게임계 3대 해악 중 하나인 울궈먹기이다).
1. 로그화일 활용 레이디안은 거의 모든 디버깅을 노가다로 해결했다. 도스시절부터 프로그래밍을 해오던 사람들은 요즘 나오는 바운스체커니 디버거니 하는 것들의 사용법에 대해서는 그리 익숙 하지 않을 것이다. 필자도 마찬가지인데.. 레이디안때는 더더욱이 경험이 부족한 때라서 디버깅에 많은 힘을 기울였고, 대부분이 노가다 디버깅이었다. 버그가 일어나는 곳에서 Log화일을 사용하여 현재 상태를 출력함으로써 논리상 버그를 찾았던 것이다. 타기종등 하드웨어 호환성 검사시에도 이 로그화일은 매우 활용도가 높을수 있다.
2. 메모리 누수를 막아라. 레이디안때도 그랬고, 씰때도 그랬고, 크러쉬 작업할때도 마찬가지 였지만, 메모리 누수 는 정말 사람을 돌아버리게 하는 버그이다. 메모리 누수는 정말 세심히 체크하지 않으면, 안돼는 부분이라... 여기서 그때 알아낸 노하우를 약간 써보자. 일단, 포인터사용을 최대한 줄인다. 크기를 미리 알수있는 것은 무조껀 배열로 만들고, 동적인 할당이 필요한 것만 포인터를 사용한다. 포인터는 정말 메모리 잡아먹는 귀신이다. 두번째로, 포인터변수는 항상 초기화를 NULL로 시킨다. NULL인지 아닌지로 해당 변수에 메모리가 할당되었는지 아닌지를 체크할 수 있다. 세번째, 포인터변수는 사용되지 않는 순간 즉시, NULL인지 확인하고 delete한다. 네번째, 포인터변수를 사용하는 클래스는 파괴자에 모든 포인터변수의 메모리를 free하 도록 신경써준다. 포인터변수 안에 포인터변수가 들어있을 경우에는 더더욱이 loop를 돌 면서 확실히 메모리를 비워줘야한다. 다섯번째, 맵등 자주 메모리를 재할당하는 클래스의 경우, 내부변수만 새로 읽는 것이 아니라, 확실히 클래스를 지우고 새로 읽어들이는 편이 낫다. 메모리에 쓰레기값이나 이 전정보를 가지게 되는 경우가 종종있는데, 확실히 초기화하지 못할 바에는 클래스자체를 지우고 새로 생성하는 편이 낫다. 이것은 최적화와는 완전히 반대되는 것으로 최적화중 가장 중요한 것중 하나는 과도한 메모리 블록의 할당 및 제거이다. 이를 적절히 사용하는 것이 디버깅과 최적화의 지름길일 것이다.
3. 출시 3개월전부터는 코드구조를 바꾸지 마라. 이건 절대 지켜야할 문제이다. 코드를 안정화 시키려면, 최소 3개월이전부터 설계된 구조를 바꾸는 일을 해서는 안됀다. 왠만하면 처음 설계한 코드대로 게임을 끝까지 작성하면 좋으련만... 사람일이 뜻같지 않 아서, 그렇게는 안됀다. 언제 어떤일로 설계가 변경될지 모르게 된다. 그렇지만, 출시 3개 월전에 코드의 설계를 변경하게되면, 치명적인 버그가 생길 수 있다는 점을 명심하기 바 란다. 그리고 최소 1개월은 코드의 추가가 있으면 안됀다. 기능의 추가라든가 하는것은 1 개월전부터는 최소화하고 절대적으로 코드 안정화와 최적화에 힘을 기울여야한다.
4. 오류체크는 잊지마라. 보통 최적화를 위해 오류체크부분을 없애는 경우가 종종있다. 하지만, 프로세스타임을 많이 잡아먹는 그래픽 출력부분을 제외한 논리적인 부분에서 오류체크를 안하게되면, 코 드의 안정성은 심각하게 타격을 받게된다. 메모리가 할당되었는지, 메모리가 제대로 free 됐는지 여부등은 확실히 오류를 체크해줘야한다. 대부분의 게임이 이러한 부분에 최적화 랍시고 오류체크를 빼는 바람에 막바지에 고생하게 되어버리고 만다. 논리적인부분에서는 오류체크를 한다고 해도 느려지지 않는다. 버그로 뻗는 것보다는 조금 느린 편이 낫다고 생각하지 않는가?
5. 최적화에 목숨걸지 말자. 위의 말과 일맥상통하는 말이다. 논리적인 알고리즘적 최적화를 제외하고, 오류체크라든 가, 루프등을 없앰으로써 얻는 최적화의 효과는 극히 미미하다. 알고리즘을 분석하고 알 고리즘자체를 변경시키는 편이 훨씬 낫다. 알고리즘을 변경할 수 없다고 종종, 디버깅하 기 어렵게 오류체크라든가, 루프없애기, 암호문 만들기(어디서보니 코드를 압축하면 빨라 진다고 한다.) 등을 하는 사람들이 있는데, 그런데 노력하느니, 출력알고리즘 자체를 조금 이라도 손보는 편이 정신건강상 이롭고, 디버깅도 쉬워진다.
6. 최적화는 최후에 최적화는 디버깅이 어느정도 끝나고 코드가 안정화 된 시점에서 해야 한다. 코드가 안정 화되지 않은 시점에 최적화를 하게되면, 버그가 갑자기 많아져버리게 되는 경우가 종종 있다. 절대로 최적화는 최후에 하라. 최적화가 덜되었다고 게임이 재미없는 것은 아니다. 하지만, 디버깅이 덜되면, 게임은 재미없어진다. 코드를 작성하는 것보다 디버깅이 어렵다.
7. 설계를 확실히, 그리고 디버깅이 가능하도록 코드를 작성하자. 설계를 바꾸지 않아도 되도록, 클래스들을 설계할때 여러가지를 생각하고, 기획서를 숙 지하고 만들도록 한다. 부실한 설계는 프로그램을 필요이상으로 복잡하게 만들게 되고, 그것은 버그를 양산하는 길이다. 최초설계를 튼튼히 하도록한다. 그리고, 처음부터 디버깅 이 가능하도록 코드를 작성하도록한다. 코드를 너무 암호문으로 길게 작성한다던가 한다 면, 나중에 가독성이 떨어져서 디버깅이 나쁘다. 디버깅이 끝난 시점에서는 코드를 짧게 줄일 수도 있겠지만, 처음에는 가독성 위주로 코 딩하는 습관을 기른다.
8. 릴리즈 모드 컴파일을 자주한다. 어차피 게임은 절대 디버그 모드로 출시할 수 없다. 속도 문제도 있지만, 해킹 등의 문 제로 인해 디버그 모드로 출시하면 절대 안돼는데, 출시 한두달전에 릴리즈 컴파일을 시 작한다면, 상당한 버그에 골머리를 앓을 것이다. 분명 디버그시에 없던 버그들이 줄지어 나오기 마련이다, 레이디안 작업시에 상당히 골머리 아팠던 부분이었다. 실제로 레이디안 은 디버그 최적화 모드로 출시했다. 물론 지금은 VC에 디버그 최적화 모드가 삭제되었기 때문에 절대적으로 릴리즈모드로 출시해야한다. 릴리즈모드는 제작 초기부터 코드가 조금 안정되었다 싶으면 바로 바로 컴파일하고 테스트를 해봐야 한다. 단계별로 새로운 코드가 추가될때마다 릴리즈 컴파일을 해봐야 버그를 쉽게 발견할 수 있지, 그렇지 않고서는 수 십만줄에 달하는 소스안에서 절대로 버그를 찾아낼 수 없다. 모든 것은 차근차근 단계를 밟아 나가야 하는 것이다.
9. 함수호출을 자제하라. 보통 함수를 무척 다단계로 만드는 사람들이 있다. 하나의 함수가 작동하는 것을 따라가 려면, 최초 호출 (WinProc 또는 WinMain)에서 10번 이상 함수에 함수가 꼬리를 무는 경 우가 종종있는데, 이는 피해야 하는 것중 하나이다. 웬만한 코드는 직접 외울수 있다고 하지만, 이정도 코드가 되어버리면, 작업을 1년 쯤하다가 다 까먹어버리고 만다. 결국 디 버깅할 때 함수 쫓아서 F11키 누르다가 볼일 다 보게 되는데, 이것은 재귀호출만큼 디버 깅을 어렵게 하는 것이다. 왠만하면 함수호출은 자제하는 습관을 기르도록 하는 것이 좋 다.
함수의 길이는 짧게 쓰는 사람 길게 쓰는 사람 각양각색인데, 최적화를 위해서 함수호출 오버헤드조차 줄이기 위해서 함수를 길게 쓰는 사람도 있다. 물론 좋은 방법이긴 하지만, 많이 호출되지 않는 함수는 그렇게 할 필요가 없고, 그래픽 출력, 애니메이션 등 많이 사 용되는 부분에서 여러 번 함수를 호출하지 않도록 하는 것이 함수호출 오버헤드도 줄일 수 있고, 디버깅도 쉬워지는 일거양득을 얻을 수 있다.