안녕하세요. 소프트웨어 엔지니어 권형우입니다. 이 글에서는 게임 개발에서 결정론적인 알고리즘을 살펴봅니다.
결정론적인 알고리즘에 대해
결정론적인 알고리즘은 같은 맥락에서 같은 입력을 수행했을 때 같은 결과를 냅니다. 다음은 용감한 쿠키의 움직임으로 결정론적인 알고리즘을 표현한 예시입니다.
용감한 쿠키가 (0, 0) 위치에서 출발
- 용감한 쿠키가 (5, 0)만큼 이동 -> 위치 (5, 0)
- 용감한 쿠키가 (0, 5)만큼 이동 -> 위치 (5, 5)
- 용감한 쿠키가 (-5, -5)만큼 이동 -> 위치 (0, 0)
용감한 쿠키의 최종 위치는 (0, 0)
용감한 쿠키가 같은 위치에서 출발해서 같은 양만큼 움직였다면 몇번을 반복해도 용감한 쿠키의 최종 위치는 같습니다. 게임이 이런 결정론적인 알고리즘으로 구현되어 있다면 같은 입력은 같은 결과를 나타낸다는 근거로 여러 기능들을 구현할 수 있습니다.
결정론적인 알고리즘의 구현
고정 프레임 게임 루프
게임에는 게임 루프가 존재하고 대체로 입력 → 게임 로직 → 화면 그리기 순서로 수행됩니다.
이 단위를 프레임 이라고 하며 초당 프레임이 지나간 횟수를 FPS (Frames Per Second)
라는 단위로 표현합니다.
게임에는 시간에 의존적인 코드 작성이 필요할 수 있습니다. 물체의 이동이나 시간 계산처럼 시간의 흐름에 따라 변화하는 게임 상태를 구현하기 위해 게임 루프에서 프레임이 처리되는 시간을 계산하고 활용합니다. 이를 프레임 처리 시간이라고 하겠습니다.
프레임 처리 시간은 기기 성능이나 게임 상태에 따라 매 프레임 다른 시간을 가집니다. 프레임 처리 시간이 매 프레임 달라진다면 게임 양상이 비슷하게 흘러갈 수는 있으나 결정론적으로 진행되지는 않습니다. 프레임 처리 시간이 달라짐에 따라 매 프레임 게임 상태에 다른 변화가 생기게 되고 달라진 게임 상태는 다른 결과를 만들 수 있기 때문입니다.
같은 입력에 대해 매번 같은 결과를 가지게 하는 결정론적인 알고리즘을 위해 게임 로직을 고정된 횟수대로 수행하는 고정 프레임 게임 루프를 사용할 수 있습니다. 고정된 시간 주기로 수행되는 게임 루프를 만들어서 항상 같은 프레임 처리 시간을 가지게 해 기기 성능에 상관없이 같은 결과를 가지게 합니다.
게임 루프를 고정된 주기로 수행하는 고정 프레임 게임 루프를 사용하면 게임 로직 수행 주기와 화면 갱신 주기에 차이가 생깁니다. 화면 갱신 주기는 하드웨어에서 정해진 주기를 따라가는데 게임 로직 수행 주기는 하드웨어에 관계 없이 고정 프레임 게임 루프에서 정해진 주기대로 수행되기 때문입니다. 화면 갱신 주기에 맞춰 고정 프레임 게임 루프를 사용하기 위해 예측을 구현할 수 있습니다.
예측이란 마지막으로 갱신된 게임 로직 수행 상태에서 다음 프레임 사이 화면 갱신 주기에 현재 상태를 예측하여 화면에 표현하는 작업입니다. 물체의 움직임이나 애니메이션처럼 화면에 보여지는 것들에 대해 예측을 구현해 고정 프레임과 다른 화면 갱신 주기를 가지는 기기에서도 화면 갱신 주기에 맞춰진 게임 상태를 표현할 수 있습니다.
랜덤
게임에는 확률적으로 진행되는 것들이 있습니다. 확률적으로 진행되는 요소들을 결정론적으로 구현하기 위해 시드값을 넘겨받아 초기화하는 랜덤을 사용합니다. 시드값이 같다면 생성되는 난수도 같은 결과를 가지게 되어 확률적인 동작들을 결정론적으로 구현할 수 있습니다.
마무리
게임 코드를 결정론적으로 작성하면 기기 성능에 영향을 덜 받는 결과를 만들 수 있고 개발 환경에 도움을 줄 수 있습니다. 또한 결정론적인 알고리즘이 뒷받침되어야 구현할 수 있는 기능들도 존재합니다.
게임을 개발할 때 필수적인 요소는 아니지만 상황에 따라 많은 도움을 줄 수 있습니다. 현재 진행중인 프로젝트에 어울리는지 혹은 활용할 여지가 있는지 살펴보고 적용하여 프로젝트를 발전시킬 수 있습니다.