카테고리 없음

[펌] 모바일 3D 게임을 만들자②

achivenKakao 2005. 3. 12. 19:59
[모바일 3D 게임을 만들자] ② 게임 설계
조종근, 구병기 (마이크로소프트웨어 필자)
2004/08/11
3D 게임을 만든다는 것은 그리 쉬운 일이 아니다. 더군다나 모바일 환경에서 3D 게임을 만드는 것은 많은 노력과 경험을 필요로 하는 작업이다. 예를 들어 작은 화면에 게임의 특성을 갖추면서도 3D 게임이 제공하는 현란함을 넣으려고 한다면 아직 개발 환경과 대상 모바일 기기가 많이 뒤쳐져 있음을 실감하게 될 것이다.

하지만 모바일 게임이 3D를 만나면서 이러한 노력들은 조만간 빛을 볼 것으로 보인다. 단말기 안의 칩을 만드는 많은 칩 제조사가 3D 가속기를 단말기 안에 넣을 수 있도록 제품을 출시하고 있고, 이동통신 사업자들은 이러한 업계의 움직임을 수용하려는 움직임이 강하기 때문이다.

3D 게임은 기본적으로 많은 양의 메모리와 CPU 리소스를 요구한다. 따라서 독자들이 3D 게임을 만들자고 한다면 당장 어느 정도의 스펙에 맞춰야 하는지에 대해 가장 궁금해 할 것이다. 그러나 이러한 고민들은 그리 바람직한 것은 아니라고 말하고 싶다. 왜냐하면 컨텐츠가 얼마나 잘 만들어졌느냐에 따라서 대상 단말기를 얼마든지 변경할 수 있기 때문이다(물론 PC용 게임을 그대로 넣는다는 것은 아직은 무리다).

일단 5년여 전의 PC 환경을 생각해 보자. 그 환경에서 돌아가는 게임을 만들어 본 경험이 있다면 앞으로 나올 단말기들에서는 그 정도 수준의 프로그램은 무리 없이 돌아갈 수 있다는 판단을 내릴 수 있다. 모바일 3D 게임 개발을 위해 현재의 단말기에 대한 더 구체적인 가이드라인이 필요하다면 컨텐츠는 2~8MB 정도가 필요하며, 런타임 메모리는 1~4MB 정도로 생각하면 좋을 듯하다. 하지만 이것도 딱 잘라 말하기 어려울 정도로 시장 상황은 급격하게 좋아지고 있다.

지난 글에도 언급한 것처럼 한 가지 주의할 사항은 어떤 형태의 모바일 게임을 만들 것인가에 대한 고려이다. 다시 말해 모바일 3D 게임은 크게 다운로드형 게임, 임베디드형 게임, PDA 또는 콘솔 게임기 형태로 나눌 수 있다.

다운로드형 게임은 다운로드 플랫폼을 이용해 개발된 게임으로, 이를 위해서는 3D 엔진이 소프트웨어적으로 구현되어야 이용할 수 있다(현재 사용자들이 갖고 있는 대부분의 단말기가 성능이 낮은 CPU를 기반으로 사용되고 있기 때문에 실제로는 최신 휴대폰을 가지고 있어야 3D 효과를 내는 게임들을 이용해 볼 수 있다). 임베디드형 게임으로는 휴대폰이 출시될 때 주로 번들로 제공되는 게임으로 다운로드형 게임에 비해 단말기에 최적화된 형태로 게임이 제공될 수 있다(PDA 또는 콘솔 게임기의 게임은 사실상 하드웨어 사양에서 PC 게임과 큰 차이가 없으므로 생략한다).

일단 3D 게임을 어떻게 만드는지 살펴보자. 그 다음에 자신이 만들려고 하는 컨텐츠가 어느 정도의 사양을 필요로 하는지 역으로 생각해 보는 방법도 나름대로 적절한 방안이다. 그냥 단말기가 나오기를 기다리기에는 너무 시간이 아깝지 않은가? 하드웨어 사양에 대한 고민을 앞세우기보다 실질적으로 3D 게임을 만드는 과정에 대해서 생각하는 것이 더 개발자다운 자세가 아닐까 싶다.

3D 게임의 기획
<그림 1>을 보면 알 수 있듯이 3D 게임이라고 해서 2D 게임과 전혀 다른 프로세스를 갖지는 않는다. 오히려 프로세스 자체만 본다면 거의 차이가 없다. 다만 게임을 운영하는 방법과 기획 의도들이 조금 달라질 뿐이다. 기본적으로 게임 기획은 <표 1>의 순서대로 진행된다.

<그림 1> 기본적인 게임 설계

 <표 1> 게임기획의 기본순서 

Game summary(게임 요약)

Game back story - 비하인드 스토리
Game description - 게임 설명
Game object inventory - 게임 캐릭터 및 아이템 설명
Game functionality overview - 게임 기능 설명

Game action sequence(게임 진행 순서)

The game action flowchart - 게임 진행 플로우차트
The screen summary - 게임의 각 화면 요약(스토리보드 or 콘티)
Screen moke up - 실제 게임 화면 구성

Graphics specification(그래픽 디테일)

Game creative statement - 디자인적인 고려 요소
Artwork orientation - 디자인 오리엔테이션
Target platform - 타겟 플랫폼
Estimated object count - 예상 캐릭터 개수
Artwork screen resolution and playfield size - 해상도 및 화면 사이즈
Artwork color depth - 사용할 컬러 개수
Artwork file format(s) - 그래픽 파일 포맷
Artwork filenaming scheme - 파일 네이밍 규칙
Artwork color palette - 컬러 팔레트
Artwork gamma level - 감마 레벨
Artwork object dimensions - 캐릭터의 사이즈
Frames per object - 캐릭터당 프레임 수
Object actions and facings - 캐릭터의 동작 구성
Game text font(s) - 사용 폰트
Miscellaneous art direction - 기타 디자인적인 고려 사항

Technical restrictions and stipulations(기술적 제약 사항)

여러 가지 기술적 제한 사항

Project schedule(프로젝트 스케쥴링)

프로젝트 시작 일자
디자인 초안 일자
제시된 디자인에 대한 프로그래머의 구현 가능성 피드백
피드백에 따른 디자인 수정 일자

Game glossary(게임에 쓰이는 용어 요약)

게임 내에서 사용되는 용어 정리


우선 게임의 배경이 되는 스토리를 설정해 보자. 플레이어로 하여금 최대한 캐릭터에 감정이입하도록 하기 위해 게임 캐릭터에게 독특한 캐릭터(?)를 부여하는 것도 좋은 방법이라고 생각한다. 내용은 각자 생각하기에 따라서 더 멋진 내용을 생각해 볼 수도 있겠지만 우선 다음과 같다고 설정해 보자.

1 게임 시나리오 작성(스토리보드 작성) - 전반적인 게임 내용
2 게임 로직 설계(프로그래밍 로직 설계) - 실제 제작될 프로그램의 뼈대와 세부 내용 설계
3 게임 로직에 들어갈 리소스 준비 - 그래픽 리소스 및 오브젝트, 사운드 파일 준비
4 게임에 사용될 구조체, 변수 등 선언 - 게임에 필요한 구조체와 설정 값 설계
5 메인 게임 루프 작성 - 인트로, 캐릭터 선택, 메인 게임 등의 게임 루프 작성
6 게임 로직 삽입 - 게임 루프 속의 실질적인 내용 삽입
7 게임 그래픽을 로직에 맞게 설계 - 게임 로직에 적절하게 그래픽 루틴을 삽입
8 키 이벤트를 게임 로직에 맞게 삽입 - 로직에 따른 키 이벤트 삽입
9 사운드 및 게임 퀄리티 향상을 위한 작업
10 게임 디버깅, 테스트
11 게임 개발 완료

이와 같은 설정도 모바일 게임에서는 특별히 필요하지는 않다. 인트로 동영상을 제공할 수 있는 것도 아니고, 개략적인 스토리를 글자로 스크롤해서 플레이어로 하여금 읽으라고 할 수도 없기 때문이다. 다만 게임 제작시 기획자나 제작자가 이런 식의 상황 설정을 하고서 게임을 만든다면 좀 더 상상력을 발휘하기가 쉽지 않을까(필자만의 방법론일 수 있겠지만…).

이런 상황 설정이 아니라면 사실 ‘스페이스큐브(spaceCube)’라는 게임의 주인공들인 곰돌이나 강아지가 우주로 나가서 네모난 큐브를 다 밟아야 할 이유는 아무 데도 없다. 이러한 상상력을 바탕으로 게임을 제작하고 플레이어들에게 그러한 상상을 조금이라도 느낄 수 있다면 게임 제작 의도는 성공적이라 말할 수 있다. 실제로 게임을 중심으로 간단하게 설계해 보면 <그림 2>처럼 그려볼 수 있다.

<그림 2> 전제적인 게임 로직 설계

<그림 3> 스페이스큐브의 게임 흐름도

스페이스큐브 게임 설명
기본 스토리는 간단하다. 동물 친구 ‘곰돌이’와 ‘강아지’가 우주여행을 하던 도중 맞닥뜨리게 된 공간, 스페이스 큐브. 스페이스 큐브는 한번 들어오면 그냥은 나갈 수 없는 공간이다. 차례차례 미로와 같은 큐브의 징검다리를 통과해야지만 벗어날 수 있다. 우주 공간의 좁은 길에서 벌어지는 곰돌이와 강아지의 목숨을 건, 물러설 수 없는 한 판의 사투가 펼쳐진다. 게임 방법을 간단하게 정리하면 다음과 같다.

<그림 4> 게임 프로세스에 따른 플로우차트

1. 시작 버튼을 누르면 두 가지 게임 캐릭터 중 하나를 선택할 수 있는 화면이 나온다.
2. 화살표 키를 이용해 캐릭터를 선택한 후 확인 버튼을 누르면 초기화면이 셋팅되고 게임이 시작된다.
3. 캐릭터가 한 칸씩 큐브 위를 이동해 나갈 때마다 점수가 올라가고 큐브 색깔이 바뀐다.
4. 게임 진행 중 황색 함정 큐브를 밟거나 시간 제한에 걸리면, 또는 큐브 위를 굴러다니는 불공을 만나면 목숨을 잃게 된다. 초기에 주어지는 목숨은 3개이다.
5. 시간 내에 무사히 모든 큐브를 밟고 통과하게 되면 라운드가 끝나고 다음 스테이지가 셋팅된다.

<화면 1> 3D 이미지로 표현된 게임의
주인공, 곰돌이와 강아지

<화면 1><화면 2> 리소스 사용을 줄이기 위해
게임의 배경 화면은 2D로 처리했다.

개발자 입장에서 3차원 게임의 특징을 잘 살릴 수 있는 요소는 미로와 같은 큐브를 진행하면서 볼 수 있는 공간감을 최대한 살리는 것이 아닐까 싶다. 플레이어의 캐릭터는 플레이어의 조작에 따라 전, 후, 좌, 우로 이동해야 하는데 이때 3차원의 공간감을 많이 느낄 수 있어야 한다. 공간감은 게임 시작 초기에 여러 각도의 카메라 작업이나 줌인, 줌아웃을 통해 먼저 시범적으로 보여주는 것도 좋을 것이다.

 <표 2> 스페이스큐브의 사운드 설정 

파일명

사이즈(KB)

재생시간(sec)

Ready.wav(Ready)

18.5

1

StgClear.wav(Stage Clear)

242 

5

TimeOver.wav(Time-out)

9.04

0.8

Opendoor.wav

41.8

1

FallSound.wav(Falling)

87.1

4


게임 기획 의도
플레이어는 곰돌이와 강아지를 조종하도록 하고, 큐브는 미로와도 같이 설정한다. 플레이어(곰돌이 또는 강아지)는 스페이스 큐브를 모두 정복해야 스테이지를 클리어할 수 있다. 모바일 게임인 만큼 복잡하게 머리를 써야 하거나 생각을 요구하기보다는 순발력과 순간 판단력이 요구되도록 게임을 기획했다. 스테이지는 점점 더 난이도를 높이되 스테이지가 진행될수록 조작의 능숙도만 높아지면 클리어할 수 있다.

장기나 체스처럼 여러 가지 조합의 수를 생각하면서 게임을 진행하는 게 아니라 큐브가 더 커지고 시간은 점점 더 촉박하게 만드는 단순한 구조이며, 속도를 차츰 빨라지도록 해 플레이어의 흥미를 유발한다. 플레이어로 하여금 큐브를 돌파해서 스테이지를 클리어하게 하는 단순한 목적을 성취하도록 유도함으로써 게임의 흥미를 높이는 단순한 방식이다. 그러나 플레이어가 게임을 거듭할수록 캐릭터 조작이 능숙해지며 더 빨리 길을 찾고, 함정을 잘 피할 수 있게 됨에 따라 업그레이드되는 기분을 맛볼 수 있도록 했다.

어떤 유형의 게임이든 목적성을 가진다면 플레이어가 이를 이루려는 욕구가 생긴다. 예를 들어 갤러그와 같은 고전 슈팅 게임은 단순히 비행기를 격추하는 것이지만 이것이 전부라면 금방 흥미를 잃고 만다. 갤러그는 플레이어로 하여금 두 가지 목적의식을 갖게 한다. 가장 기본적인 한 가지는 점수 획득, 높은 점수를 획득하면 스코어 랭킹에 이름을 올릴 수 있다. 다른 한 가지는 스테이지의 클리어 기능이다. 한 판을 모두 깨면 다음 판으로 넘어간다(예전에 게임을 할 때 친구들과 서로 몇 판 깼냐고 물어보면서 스테이지 수치로 비교해 본 경험이 있을 것이다).

이제 남은 것은 실전 게임 소스 분석!
마지막으로 스페이스큐브의 주요 소스를 살펴보자. <리스트 1>과 <리스트 2>는 최신 버전인 G3 SDK 1.6.1으로 앞에서 설명한 스페이스큐브 게임을 실제 코딩했을 때 골격이 되는 부분이다. main 부분의 pseudo 코드는 <리스트 1>과 같다. <리스트 2>는 UpdateGame과 InitGame 부분의 pseudo 코드이다.

 <리스트 1> 스페이스큐브의 main 예제

void G3_Main(void *arg)
{
    int k;
    int ExKey;
 
    for (k = 0 ; k < 2 ; k++)G3_LcdSurfaceGet(&g3Draw[k], k);  
                
    G3_SurfaceSet(&g3Draw[0]);  
    nflip = 1;
    ReSizeGLScene(G3wWidth, G3wHeight);
    InitGame() ;
 
    while(1)
    {           
        if ( SynchFrame () )  // 프레임 조절
       {        
        // 키 처리 부분
        G3_KeyGetEx(&ExKey);
        switch(GAME_STATE)
        {
            case PUZZLE_START:
                // 게임 시작 루틴 부분 코딩(키패드 관련)
            break;
            case PUZZLE_CHOOSE:
                // 게임 캐릭터 선택 부분 코딩(키패드 관련)
            break;
            case PUZZLE_MAIN:
                // 본 게임 메인 부분(키패드 관련)
            break;
        }
 
        UpdateGame(GAME_STATE); // 게임 루프(그래픽 관련)
                   
        G3_SurfaceFlip(&g3Draw[nflip]); // Back 버퍼의 값을 Primary 버퍼로 플립핑(더블 버퍼링)
        nflip = (nflip + 1) & 0x01;     // nfip 변수를 셋팅
        }
      }
}

 <리스트 2> UpdateGame과 InitGame 예제

// 게임의 그래픽 부분, 즉 화면에 뿌려지는 모든 부분을 관리한다.
void UpdateGame(GAME_STATE)
{
        switch(GAME_STATE)
        {
            case PUZZLE_EXIT::
                // 게임 종료
            break;
            case PUZZLE_START:
                // 시작 루틴 부분 코딩
            break;
            case PUZZLE_CHOOSE:
                // 게임 캐릭터 선택 부분 코딩(키패드 관련)
            break;
            case PUZZLE_MAIN:
                // 본 게임 메인 부분(키패드 관련)
            break;
        }
}
 
// 게임 시작을 위해 초기화 작업을 한다.
int InitGame(void)
{
        // 아바타 개수 설정
        nAvatarNum = 2;
        G3_3DgCreate((unsigned char)nAvatarNum)
        // 텍스처 로딩
        // 사운드 로딩
        // 게임 시작
        GAME_STATE = PUZZLE_START;
 
        return 0;
}

지금까지 스페이스큐브를 통해 모바일 3D 게임 개발 과정을 개괄적으로 살펴보았다. 필자의 사정으로 예제에 대해 충분히 설명하지 못했는데 널리 양해해 주기 바란다. 다음 호에는 pseudo 코드가 아닌 스페이스큐브의 실제 게임 소스를 통해 더욱 구체적이고 실질적인 프로그래밍 과정을 살펴보기로 하겠다. @