옛날 게임프로그래밍을 공부할 초창기에 간단한 RPG 를 만들어보려고 한 적이 있었다.

맵타일, 스프라이트로 화면 출력을 하거나, 입력을 받거나 하는 것은 그렇게 어려운 문제가 아니었는데

가장 쉽지 않은 문제는 마을 사람들의 행동에 대한 로직을 구현하는 것이었다.


예를 들어 마을의 무기상점 주인을 구상해보자. 단순히 한곳에 머물러 있다가 말을 걸면 대답을 하는

것이 아니라, 스스로 어떤 스케쥴을 갖고 움직이는 것을 구현해보자. 이 무기상인은 자기 집에 머물러

있다가 아침이 되면 가게에 나와 문을 열고 가게를 오픈해서 가게를 지키다가 저녁이 되면 가게문을 닫고

술집에 들러 노닥거리다가 밤이 되면 집에 들어와 잔다고 가정하자. 이런식의 시간에 따른 움직임은

옛날 울티마6 같은 게임에서 영향받은 것이다.


무기상점.script

while (1) {
    Goto("상점");
    OpenShopDoor();
    DoWorkUntil(5pm);
    LeaveShop();
    CloseShopDoor();
    Goto("술집");
    StayUntil(11pm);
    Goto("집");
    SleepUntil(6am);
}

이런식으로 시간의 순서에 따라 코딩을 하는 것이 가장 간단한 방법이 될 것이다.

하지만 문제는, C/C++ 의 문법체계로는 저런 로직을 바로 표현할 수 없다는 점이다. 왜냐하면 저 위의

스크립트에 등장하는 Goto 나 DoWorkUntil 같은 로직들은 함수, 서브루틴의 개념으로 표현해서는

안되기 때문이다. 만약, 저 로직을 함수로 실행하게 된다면 저 각각의 함수들은 실행하는데 아주 오랜

시간이 걸리게 될 것이며, 저 무기상인 한명의 로직을 실행하는 데에 컴퓨터의 모든 리소스가 투입될

것이다. 마을에 저 무기상인 말고도 다른 존재들은 주인공 플레이어를 포함해서 다수 존재할 것이기

때문에, 저 무기상인의 로직을 처리하면서도, '동시에' 다른 캐릭터들의 로직도 처리할 수 있도록

만들어야만 한다.


코루틴 개념이 없는 언어에서 저런 로직을 처리하기 위해서는 각각의 캐릭터에 상태의 개념으로 분리

하여 (FSM) 자신의 업데이트 차례가 돌아왔을 때 상태별 처리와 상태 전환에 대한 판단을 하도록 만들

어야 한다.


그에 반해 코루틴 개념을 이용하면 위에 기술한 각각의 로직을 그대로 코루틴으로 기술하면 된다.

코루틴은 한번에 복수개를 실행시킬 수 있고 (한번에 여러명의 pc, npc 가 마을에 존재하는 것처럼)

코루틴은 자기가 필요한 만큼의 일을 하고 재스케쥴링을 시켜줌으로써 (루아의 경우에는 yield,

stackless 의 경우에는 stackless.schedule() ) npc 하나가 cpu 를 독점하는 경우를 막을 수 있다.


위의 사례에 등장하는 Goto 같은 코루틴의 가상소스를 살펴본다면 아마 다음과 비슷할 것이다

Goto(pos Dest)
{
    SetTarget(Dest);   // 또 다른 coroutine 으로 작성된 길찾기 agent 의 목적지점을 지정
    while (1) {
        if (self.pos.IsNear(Dest)) return;
            coroutine.Yield();
    }
}

위와 같은 요령으로 어떠한 상태를 코루틴으로 작성할 수 있으며, 이러한 코루틴들은 재사용도 가능하고

코루틴을 시간순으로 열거했을때 휠씬 작성하기도, 이해하기도 쉽다.

imcgames 의 김학규입니다