2009-05-28 5 views
4

Visual C++ 2008 Express 및 Ogre3D SDK를 사용하여 게임을 프로그래밍하고 있습니다.비동기 화면으로 게임 플레이 로직 업데이트, C++

내 핵심 게임 플레이 논리가 초당 100 회 실행되도록 설계되었습니다. 간단히하기 위해 'gamelogic()'이라는 메서드라고 말합니다. 시간 기반이 아니므로 게임 시간을 1 초 앞당기려면 100 회 gamelogic()을 호출해야합니다. 'gamelogic()'은 게임의 화면 렌더링과 비교하여 가볍습니다.

오우거에는 프레임을 그릴 때와 프레임을 그릴 때 코드에 알리는 "청취자"논리가 있습니다. 프레임 렌더링 바로 전에 'gamelogic()'을 호출하면 게임 플레이가 5fps에서 120fps까지 다양 할 수있는 화면 렌더링 속도의 영향을 크게받습니다. 마음에 오는

쉬운 솔루션입니다 : 마지막으로 렌더링 된 프레임 이후의 경과 시간을 계산하고 '() gamelogic'다음 프레임 전에이 여러 번 전화 : 그러나 100 * timeElapsedInSeconds

을, 그 pressume은 " 옳은 "방법은 멀티 스레딩을 사용하는 것입니다. gamelogic() '을 100 번/초 실행하는 별도의 스레드가 있어야합니다.

Ogre가 동시에 화면을 렌더링하는 동안 gamelogic 화면 내용 (3D 객체 좌표)이 서로 다른 두 스레드 사이에 충돌이있을 때 어떻게 할 수 있습니까?

미리 감사드립니다.

답변

6

첫 번째 게임 응용 프로그램 인 경우 결과를 얻기 위해 멀티 스레딩을 사용하면 첫 번째 게임에서 실제로 다루어야 할 것보다 많은 작업이 필요할 수 있습니다. 게임 루프를 Sychronizing하고 다른 스레드에서 루프를 렌더링하는 것은 쉬운 문제는 아닙니다.

올바르게 지적하면 렌더링 시간이 게임의 "속도"에 크게 영향을 줄 수 있습니다. 게임 논리를 설정 한 시간 조각 (예 : 1/100 초)에 종속시키지 않는 것이 좋습니다. 현재 프레임 시간 (현재 프레임이 렌더링하는 데 걸리는 시간을 모르기 때문에 마지막 프레임 시간)에 종속되게 만듭니다.

일반적으로 나는 다음처럼 작성할 수 (내가 쓴 크게 단순화 입니다) :

float Frametime = 1.0f/30.0f; 
while(1) { 
    game_loop(Frametime);  // maniuplate objects, etc. 
    render_loop();    // render the frame 
    calculate_new_frametime(); 
} 

프레임 - 타임은 현재 프레임이 갔다하는 calculcated 프레임 - 타임이입니다. 게임 루프를 처리 할 때 이전 프레임의 프레임 시간을 사용하고 있습니다 (1/30 또는 1/15 초와 같이 합당한 값으로 초기 값을 설정하십시오). 이전 프레임 시간에 실행하면 필요한 결과를 얻을 수있을만큼 근접합니다. 그 시간 프레임을 사용하여 게임 루프를 실행 한 다음 물건을 렌더링하십시오. 게임 루프의 로직을 일정한 시간 간격을 갖지 않도록 변경해야 할 수도 있지만 일반적으로 그러한 종류의 수정은 매우 쉽습니다.

비동기 게임/렌더링 루프는 궁극적으로 필요한 것이지만 해결하기가 힘든 문제입니다. 오브젝트 및 관련 데이터의 스냅 샷을 작성하고, 해당 스냅 샷을 버퍼에 넣은 다음 버퍼를 렌더링 엔진에 전달합니다. 그 메모리 버퍼는 게임 루프가 렌더링 루프를 읽는 동안 그것에 쓰기를 피하기 위해 중요한 섹션 주위에 올바르게 분할되어야합니다. 렌더 루프에 전달하기 전에 모든 관련 데이터를 버퍼에 복사해야합니다. 또한, 게임이나 렌더링 루프를 멈추게하는 로직을 써야 하나가 완료 될 때까지 기다릴 수 있습니다.

이 복잡성 때문에 처음에는 좀 더 직렬 방식으로 작성하는 것이 좋습니다 (경험이없는 한). 그 이유는 먼저 "쉬운"방법을 사용하면 코드가 작동하는 방식, 렌더링 엔진이 작동하는 방식, 렌더링 엔진에 필요한 데이터의 종류 등을 배워야합니다. 복잡한 게임 개발에는 멀티 스레딩 지식이 필요합니다 요즘에는 게임 시스템이 어떻게 상호 작용하는지에 대한 깊은 지식이 필요합니다.

+1

게임은 고정 렌더링 속도 가정에서 잠시 전에 프레임 시간을 추적하는 것으로 전환되었습니다. 이전에는 프로세서가 8 Hz에서 실행된다는 것을 알고있었습니다. 16Hz 장비가 출시되었을 때 프로세서를 16Hz에서 8Hz로 전환 할 수있는 '터보 버튼'이 포함되어있어 게임이 여전히 올바른 속도로 작동 할 수있었습니다. 재미있는 사실. – Kieveli

+0

사실! 오래된 게임이 새로운 컴퓨터에서 허용되는 프레임 속도로 실행되도록 프로세서를 "감속"하도록 작성된 작은 응용 프로그램조차있었습니다. 하나는 "MOslo"라고 불렀습니다. 내가 가지고있는 최신 컴퓨터에서 너무 빨리 실행되는 모든 오래된 Ultima 게임을 기억합니다. – Mark

+1

터보 파스칼 런타임에서는 빠른 머신에서 실행될 때 정수 오버플로가 발생하여 모든 것을 충돌시킬 수 있습니다. – tstenner

0

렌더링 가능한 개체를 두 번 버퍼링하면 탐색 할 수있는 방법입니다. 즉, 렌더링 구성 요소는 모든 게임 동작이 두 번째 버퍼의 관련 개체를 업데이트 할 때 업데이트되는 1 개의 버퍼를 사용하고 있습니다.

하지만 개인적으로 나는 그것을 좋아하지 않습니다. 저는 Mark의 접근 방법을 사용하고 싶습니다.

1

플레이어가 응답 할 수있는 것보다 빠르게 실행되는 핵심 게임 논리에 많은 이점이 없습니다. 정말 유용한 유일한 시간은 신속하고 고정 된 시간 단계로 실행하면 시뮬레이션이 더 일관성있게 작동 할 수있는 물리 시뮬레이션입니다.

그 외에도 프레임 당 한 번 게임 루프를 업데이트하고 고정 된 시간에 의존하지 않고 가변 시간 델타를 전달하십시오. 멀티 스레딩을 통해 얻을 수있는 이점은 비용 대비 최소한입니다. 특히 이것이 첫 번째 게임 인 경우 특히 그렇습니다.