본문 바로가기
책/게임

[책] 액션게임 알고리즘 매니악스

by 알 수 없는 사용자 2008. 5. 4.


사에바료님 블로그와 지나님 블로그에서 알게 된 책. 

 점프나 대쉬와 같은 이동부터 트램블린(퐁퐁)과 워프게이트 등의 장치까지, 액션게임에 등장하는 여러 피처를
소개하고 그 동작원리를 분석한 뒤, C++로 된 예제 코드로 보여주는 구성이다. 한마디로 요약하면..

'고전 액션게임의 역기획 선물세트' 다. (아니, 리버스 엔지니어링이라 해야 하나..)
 
 격투게임 피처의 역기획으로서 준비했던 격투게임피처분석이 목적하던 바도 이런 내용이었다. 이 쪽은 액션게
임에 관한 것들로, 로드런너를 할 때의 구멍파기와 메우기, 마피를 할 때의 문 여닫기와 퐁퐁 타기 등이 어떤
원리로 만들어져 있는지 설명하고 있다. 내용은 다음의 8가지 카테고리로 구성되어 있다.

Stage 01 이동
Stage 02 점프
Stage 03 기믹(장치)
Stage 04 지형이용
Stage 05 특수행동
Stage 06 무기
Stage 07 아이템
Stage 08 미션

동봉된 CD의 데이터로 소개된 피처들을 실행해 볼 수 있다.

수영
움직이는 바닥
거대화
무기교체
트렘폴린(마피)
바위 떨구기(디그더그)


 격투게임피처분석 자료를 준비할 때 카테고리를 나누기가 참 애매한 부분이 있었는데, 이 책에서도 그런
부분이 발견된다. 로프 잡기는 기믹인가 지형인가? 거대화는 특수행동인가 아이템인가? 뭐 그런 것들.
어차피 하나하나 내용이 중요하니 별로 문제될 것은 없다. 

 게임을 만드는 것에 있어서 내가 궁금해하던 것은 바로 이런 내용이었다. 어떤 게임플레이를 기획할 때 게임
에서 사용될 파라미터를 고려하고, 캐릭터나 피처의 상태를 정의하며, 게임 상황이 바뀔 조건을 판별하는 
과정 말이다. 미니게임을 기획하고 (프로그래머의 손을 많이 빌렸지만)Lua로 직접 짜고 버그를 수정해 보면서
비로소 알게 된 경험들, 이 책에서는 그런 경험들을 액션 게임에 한해서 간접적으로 체험할 수 있다. 

소개되고 있는 내용이 대부분 고전게임인데, 시티 커넥션의 페인팅이나 디그더그의 바위떨어뜨리기, 마피의
문 여닫기 등 90년대 이후에는 볼 수 없었던 시스템에 관한 내용이 여럿 준비되어 있다. 그동안 나왔던 게임
들이 어떤 아이디어를 기반으로 했는지, 또 어떻게 구현했는지 살펴보는 것은 단순한 공부가 아니라, 새로운
시스템을 생각하는 데에도 소스가 될 것이다. 

 예시 코드가 직접적으로 얼마나 도움이 될 지 프로그래머가 아니라 확실히는 모르겟지만, 파라미터와 상태,
조건 판별의 로직을 생각하는 데에는 확실히 도움이 된다. 3D를 고려하지 않았고, 객체화가 거의 되지 않은
것 같아서 프로그래머보다는 기획자에게 더 도움이 되는 책이 아닐까 생각된다. 어쨌든 한 권쯤 갖고 있으면
도움이 될 만한 물건.

 대전격투 게임은 물론, RPG의 시스템에 관해서도 이런 책이 나왔으면 좋겠다. 캐릭터 성장 시스템, 숙련도
시스템, 이벤트 설정 플래그 등등..게임을 역기획하는 것보다 훨씬 빨리 습득할 수 있을 테니 말이다. 이런
내용의 책이 2007년이 되어서야 나오는 일본의 현실도 참 슬픈 것 같다..(혹시 이전에도 이런 책이 있었는지?)

프로그래밍 모르면서 길게 늘어놓아 봤자 소용없으니 피처 하나를 번역해 본다. 프로그래밍 좀 되시는 분들
의 의견 부탁. (회사 플머분들께 보여주면 "주석이 일어야~~!"하면서 도망치셔서..)



고정길이 점프

 버튼을 누르면 캐릭터가 점프하는 액션입니다. 게임에 따라서는 레버를 뒤나 대각선 위로 입력했을 때
점프하는 것도 있습니다. 많은 경우, 캐릭터는 매끄러운 포물선을 그리며 점프합니다.
 점프를 채용한 게임에는, 점프 중에 버튼을 놓는 것에 의해 점프의 높이를 조정하는 것과 점프의 높이가
고정되어 있는 것이 있습니다. 본서에서는 전자를 가변길이 점프, 후자를 고정길이 점프로 해서 각각 해설
하기로 했습니다. 여기서는 우선 고정길이 점프에 대해서 설명합니다.

 간단하게, 우선은 정지해 있는 캐릭터가 점프하는 경우를 생각해 봅시다 (Fig. 2-1). 버튼을 누르면 캐릭터
는 점프를 개시하고, 수직으로 상승을 시작합니다 (Fig. 2-2).
 캐릭터는 상승해 갑니다만, 중력에 이끌려 점점 상승 스피드가 떨어집니다 (Fig. 2-3). 그리고 언젠가는, 상
승 스피드가 0이 됩니다 (Fig. 2-4). 이곳이 점프의 정점입니다.
 정점에 도달한 후에는 상승에서 낙하로 이행합니다(Fig.2-5). 낙하 도중에는 중력에 이끌려 점점 낙하 스피
드가 커지게 됩니다. 그리고 지면에 착지하면 점프는 종료됩니다 (Fig 2-6).
 다음으로 좌우로 이동하면서 점프한 경우에 대해서 생각해 봅니다. 종방향의 움직임은 정지해 있는 캐릭터
가 점프한 경우와 같습니다. 이것에 횡방향의 움직임이 더해짐에 의해서 점프의 궤적은 포물선이 됩니다 (Fi
g 2-7).
 점프를 사용한 게임은 굉장히 많이 있습니다. 예를 들어 '동키 콩'은 굴러오는 나무통을 점프로 피하면서
진행해 가는 게임입니다. 이 게임의 점프는 고정길이 점프로, 버튼을 놓는 것에 의해 점프의 높이를 조정
하는 것이 불가능합니다. 점프를 개시하면 점프가 종료될 때까지는 조작이 불가능하게 됩니다.
 고정길이 점프보다도 가변길이 점프 쪽이 플레이어가 자유롭게 점프할 수 있어서 쾌적한 것처럼 생각할
수 있지만, 반드시 그런 것은 아닙니다. 동키 콩의 경우에는 나무통을 아슬아슬하게 뛰어넘을 수 있는 것과
같은, 딱 알맞은 점프의 높이로 미리 준비되어 있습니다. 그 때문에, 플레이어는 점프 도중에 버튼을 누르는
것에 대해서 생각할 필요없이 점프를 하는 순간의 타이밍만을 가늠하여 버튼을 누르는 것으로 충분합니다.
결과적으로 리드미컬하게 점프 버튼을 눌러 차례차례로 나무통을 뛰어넘어 가는 것과 같은, 경쾌한 게임성
이 실현되어 있습니다.

알고리즘
 고정길이 점프를 실현하려면 점프상태와 통상상태를 구별합니다. 통상상태에서는 캐릭터를 레버로 좌우로
움직일 수 있습니다. 점프 버튼을 누르면 점프 상태로 들어갑니다. 점프의 개시 시에 캐릭터가 정지해 있었
다면 수직으로 뛰는 점프가 되고, 좌우로 움직이고 있었다면 포물선의 점프가 됩니다.
 점프를 개시하면 캐릭터에 위쪽 방향의 초속도(처음속도) 를 부여합니다 (Fig. 2-8). 예를 들어 캐릭터의 속
도를 VY라 하면, VY에 일정치의 점프 스피드를 설정합니다.

 VY = jump_speed

 점프 중에는 속도에 아래 방향의 가속도를 가합니다 (Fig. 2-9). 예를 들어 가속도를 jump_accel이라고 하면,
1프레임(1/60초 정도)마다 VY를 일정치에 가산합니다.

 VY+=jump_accel

 아래 방향의 가속도가 가해짐에 따라 어느 시점에서 캐릭터는 상승에서 낙하로 이행합니다. 이곳이 점프의
정점입니다. 정점의 높이는 처음속도(jump_speed)와 가속도의 밸런스에 의해 결정됩니다. 처음속도가 클
수록 점프는 높게, 작을수록 낮아집니다. 예를 들어 처음속도가 크고 가속도가 작으면 완만하고 높은 점프가
됩니다.

 지면에 착지했는지 어떤지를 판정하기에는 캐릭터의 Y좌표를 조사하거나, 지면과의 충돌판정처리를 실시합
니다. 지면의 높이가 고정되어 있다면 Y좌표를 조사하는 것이 간단하겠지요. 다양한 높이의 지면과의 충돌판
정 처리를 수행할 필요가 있습니다.

 좌우로 이동하면서 점프한 경우도,Y방향의 속도에 따라서는 수직 점프와 같은 계산방법입니다. X방향 (횡방
향)에 대해서는 점프개시 시 속도를 보전합니다. 예를 들어 개시 시에 X방향의 속도를 VX라 하면, 점프 중에도
속도는 VX인 채로 좌우로 이동합니다.

프로그램
 List 2-1은 고정길이 점프 프로그램입니다. 점프의 궤적을 잘 알 수 있도록, 화면을 좌우로 스크롤시키지 않는 
고정화면의 샘플로 했습니다.


// 캐릭터의 이동처리를 행하는 Move함수
bool Move(const CInputState* is) {
    // X방향의 이동 스피드
    float speed=0.15f;

    //점프의 처음속도
    float jump_speed=-0.15f;

    // 점프의 가속도
    float jump_accel=0.02f;

    // 지면에 캐릭터가 있을 때의 Y좌표
    // 착지판정에 사용한다.
    float ground_y=MAX+Y-2;

    //통상상태의 처리
    //Jump는 점프상태를 나타내는 플래그
    // true일 때는 점프상태, false일 때는 통상상태를 나타낸다.
    if(!Jump)    {
        //레버의 입력에 따라 X방향의 속도를 설정한다.
        // VX는 캐릭터의 X방향의 속도
        VX=0;
        if (is->left) VX=-speed;
        if (is->Right) VX=speed;

        //버튼을 누르면 점프상태로 이행한다.
        // 점프상태의 플래그와 처음속도를 설정한다.
        // VY는 캐릭터의 Y방향의 속도
        if (is->Button[0])    {
            Jump=true;
            VY=jump_speed;
        }
    } else

    // 점프상태의 처리
    {
        // Y방향의 속도에 가속도를 가한다.
        VY+=jump_accel;

        //Y좌표의 갱신
        y+=VY;

        // 착지판정
        // 캐릭터가 낙하중(Y방향의 속도가 일정치)으로,
        // 동시에 지면에 캐릭터가 있을 때의 Y좌표에 도달해 있다면
        // 착지한 것으로 판정한다.
        // 점프상태의 플래그를 false로 해서 통상상태로 돌아가고
        // Y좌표를 지면에 있을 때의 좌표로 설정한다.
        if (VY>0 && Y>=ground_y) {
            Jump=false;
            y=ground_y;
        }
    }
    
    // X좌표를 갱신하고 화면에서 벗어나지 않도록 보정한다.
    X+=VX;
    if (X<0) X=0;
    if (X>MAX_X-1) X=MAX_X-1;

    // X방향의 속도에 따라 캐릭터를 지향하도록 표시한다.
    Angle=VX/speed*0.1f;

    return true;
}

반응형