힘들면 쉬었다 가자.

[게임 프로그래밍 - 게임 루프]The Game Loop [1] - Koen Witters 본문

프로그래밍/기타

[게임 프로그래밍 - 게임 루프]The Game Loop [1] - Koen Witters

오클라호마호 2011. 3. 1. 16:40

 

원문보기 : http://dewitters.koonsolo.com/gameloop.html

 

 

게임 루프(The Game Loop)

 

소개(Introduction)

  게임 루프는 모든 게임의 핵심이다. 어떠한 게임이든 게임 루프 없이는 돌아갈 수 없다. 그러나 불행히도 신입 게임 개발자이 이 주제에 대해서 참조할 만한 좋은 글들이 인터넷에는 많지않다. 하지만 걱정하지 마시라, 당신은 지금 주의깊게 볼만한 게임 루프 관련글을 발견했기 때문이다.

  게임 개발자라는 나의 직업에 고맙다. 나는 작은 규모의 수 많은 모바일 게임 코드들을 봐왔고 그것은 항상 나를 놀라게 했다. 얼마나 많은 게임 루프들이 그곳에 구현되어있는지.. 당신은 아마도 그렇게 간단한 것이 다르게 쓰여질 수 있는지 궁금해 할 것이다. 글쎄.. 그것은 가능하고 나는 가장 대중적인 구현의 찬반 양론(pros and cons)에 대해서 논의 할 것이다. 그리고 내가 생각하는 최고의 게임루프 구현 솔루션을 제공해 줄 것다.


게임 루프(The Game Loop)

  모든 게임은 사용자 입력(getting user input), 게임 상태 갱신(updating the game state), AI 핸들링(handling AI), 음악과 효과음 재생(playing music and sound effects), 게임 디스플레이(displaying the game)의 시퀀스(sequence)로 구성되어진다. 이 시퀀스는 게임 루프를 통해서 핸들링(handling) 된다. 소개에서 말했듯이 게임 루프는 모든 게임의 핵심이다. 나는 이 글에서 위에 언급된 모든 작업들(tasks)에 대해서 세세한 부분까지 다루지 않고, 게임 루프 하나에만 집중 할 것이다. 나는 작업을 오직 2개의 기능으로만 단순화 시킬 것이다. : "게임 업데이트(updating the game)와 디스플레이(displaying it)"

 

다음은 가장 단순한 게임 루프의 예제 코드다.

 

 bool   game_is_running = true;

 

 while(game_is_running){
    update_game();
    display_game();
 }

 

  위의 예제의 문제는 '시간'을 다루지 않는다는 것이다. 게임은 '그냥'(just) 실행 된다. 느린 하드웨어에서는 느리게 동작하고, 빠른 하드웨어에서는 빠르게 동작(run)한다. 하드웨어의 속도가 알려진 과거에는 이것은 문제가 되지 않았지만, 오늘날에는 매우 다양한 하드웨어 플랫폼이 나와있고, 우리는 어떠한 시간 핸들링 방법(some sort of time handling)을 반드시 구현해야 한다.  이것을 위한 방법은 매우 다양하고, 그것들을 이어지는 섹션에서 논의할 것이다.

 

우선, 이 글에서 쓰이는 2개의 단어를 설명하겠다.

 

  • FPS : FPS는 'Frames Per Second'의 약자이다. 이 문맥(context)에서 그것은 초당 display_game()이 몇 번 호출되었는가를 뜻한다.
  • Game Speed : Game Speed는 초당 게임 상태가 갱신 되어진 횟수를 뜻한다. 다시 말하면, 초당 update_game()이 몇 번 호출되었는가를 뜻한다.

 

 

 

고정된(constant) 게임 스피드에 의존하는 FPS

 

구현(Implementation)

  타이밍 문제(timing issue)의 가장 쉬운 해결책(solution)은 단순히 게임의 실행을 초당 25프레임으로 꾸준히 유지시키는 것이다. 코드는 다음과 같다.

 

    const   int   FRAMES_PER_SECOND = 25;
    const   int   SKIP_TICKS = 1000 / FRAMES_PER_SECOND;

    DWORD   next_game_tick = GetTickCount();
    int   sleep_time = 0;

    bool   game_is_running = true;

 

    while( game_is_running ) {
        update_game();
        display_game();

        next_game_tick += SKIP_TICKS;
        sleep_time = next_game_tick - GetTickCount();
        if( sleep_time >= 0 ) {
            Sleep( sleep_time );
        }
        else {
            // Shit, we are running behind!
        }
    }

 

  이 방법은 엄청나게 큰 장점이 있다. 그것은 바로 단순함이다. update_game()이 초당 25번 호출된다는 것을 알고있기 때문에 게임 코드의 작성이 매우 단순하다. 예를 들면, 이러한 종류의 게임 루프에서 리플레이(replay) 기능의 구현은 매우 쉽다. 만약 게임에서 랜덤 값이 쓰이지 않는다면, 당신은 단순히 사용자의 입력 변화에 대한 로그를 남기고 나중에 그것을 리플레이 하면 된다.

 

  당신은 테스팅 머신(testing hardware)에서 이상적인 FRAMES_PER_SECOND 값을 조절할 수 있다. 그러나 빠른 하드웨어 혹은 느린 하드웨어에서는 무슨 일이 일어날까?? 글쎄.. 한번 알아보자.


느린 하드웨어(Slow hardware)
  만약 하드웨어가 정의된(defined) FPS를 처리(handle) 할 수 있으면 아무런 문제가 없다. 하지만 하드웨어에서 처리할 수 없는 경우라면 문제는 시작된다. 게임은 느리게 돌아갈 것이다. 게임에 어떤 무거운 청크(chunk : 데이터 혹은 코드 블록(덩어리) 정도로 해석하면 될 것 같음)가 있는 최악의 경우에는 게임이 정말로 느리게 돌아갈 것이고 보통의 청크라면 평범(normal)하게 돌아갈 것이다. 타이밍(timing)은 가변적(variable)으로 되어 당신의 게임을 플레이할 수 없게(unplayable) 만들 수도 있다.

 

빠른 하드웨어(Fast hardware)
  게임은 빠른 하드웨어에서 아무런 문제가 없지만, 당신은 귀중한 클록 사이클(clock cyles)을 매우 많이 낭비하게 된다. (빠른 하드웨어에서)300FPS 까지 쉽게 돌아갈 수 있는데도 게임은 25, 30FPS로 돌아간다. 부끄러운지 일이다. 이렇게 하면 당신은 매우 많은 빠르게 움직이는 객체 같은 시각소구(visual appeal : 시각에 강하게 호소하는 것)를 잃게 된다.

 

결론(Conclusion)
  고정된(constant) 게임 스피드에 의존하는 FPS 구현은 빠르게 구현할 수 있고 게임 코드를 단순하게 할 수 있는 방법(solution)이다. 그러나 이러한 방법은 약간의 문제가 있다. 높은 FPS 정의는 느린 하드웨어에서 문제를 노출할 것이다. 그리고 낮은 FPS 정의는 빠른 하드웨어에서 시각소구(visual appeal)를 낭비하게 된다.


 

---

좀 생산적인 글을 올려보자는 취지에서 시작한건데..

혹시나 번역을 잘못해서 잘못된 정보를 전달하지는 않을까

많이 걱정이 된네요..-_-;;

한 1/4 정도 끝낸 것 같은데

앞으로 계속 수정하면서 추가할 예정입니다~

 


Comments