제목이 좋지 않지만 이름을 알지 못했습니다.C++ : 게임의 총 프레임 수를 계산하십시오.
어쨌든 long int
으로 게임에서 총 프레임 수 (평균 FPS를 계산할 수 있음)를 계산합니다. 게임이 너무 오래 지속될 경우를 대비하여 내 long int
이 한도를 넘어 증가하지 않도록하려면 어떻게해야합니까? 그리고 그것이 한도를 초과하면 어떻게 될 것입니까?
감사합니다.
제목이 좋지 않지만 이름을 알지 못했습니다.C++ : 게임의 총 프레임 수를 계산하십시오.
어쨌든 long int
으로 게임에서 총 프레임 수 (평균 FPS를 계산할 수 있음)를 계산합니다. 게임이 너무 오래 지속될 경우를 대비하여 내 long int
이 한도를 넘어 증가하지 않도록하려면 어떻게해야합니까? 그리고 그것이 한도를 초과하면 어떻게 될 것입니까?
감사합니다.
전체 게임 길이의 평균 FPS는 매우 유용한 통계는 아닙니다. 일반적으로 최고 fps/최저 fps와 임계 값을 초과하는 프레임의 양과 같은 최고점과 최저점을 측정하고자합니다.
현실에서는 걱정할 필요가 없습니다. 32 비트 부호없는 int를 사용하더라도 오버플로되기 전에 19884 시간 동안 60fps로 게임을 실행할 수 있습니다. 너 괜찮을거야.
는EDIT이 경우 오버 플로우를 검출
가장 좋은 방법은 확인하고 정수 증가 후 값이 감소하는지 확인하기위한 것이다. 그렇다면 오버플로 횟수만큼 다른 카운터를 유지하면됩니다.
이 문제는 모든 종류의 카운터에 발생합니다.
귀하의 특정 문제에 대해서는 걱정하지 않으셔도됩니다.
long int
은 최악의 경우 최대 32 억 개 (32 비트 컴퓨터/콘솔에서)까지 계산됩니다. 게임이 초당 1000 프레임을 수행한다고 가정하면 카운터가 넘칠 때까지 20000000 초가 걸립니다 : 5000 시간 이상, 231 일 이상.
오랫동안 게임을 실행하려고하면 뭔가 다른 것이 게임을 멈추게 할 것이라고 확신합니다!
짧은 게임의 종류. –
@peoro 예, 약간의 계산을 직접 처리했지만,이 경우에 해당합니다. 카운터가 과도하게 증가하면 어떻게됩니까? –
@Jay : 서명되지 않은 것으로 선언 된 경우 0으로 되돌아갑니다. 그렇지 않은 경우 음수가됩니다. 이것의 정확한 효과는 코드에 따라 다릅니다. – luiscubal
산술 연산에서 오버플로를 실제로 확인할 수 있습니다. E. g. SafeInt을 사용해보세요. 물론 성능은 i++
보다 나쁩니다.
그러나 항상 1 씩 증가 시키면 32 비트 정수가 오버플로되지는 않습니다.
이 특별한 경우에는 이와 같은 제안을하지 않겠습니다. 오버플로를 피하기위한 다른 해결책은 값을 저장하는 데 더 큰 유형을 사용하는 것입니다. 'long long'또는 일부 고급 수학 라이브러리가 제공하는 동적 길이 정수까지 사용할 수 있습니다. 그러나이 경우에는 그만한 가치가 없습니다. 단지 물건을 느리게하고, 더 복잡하고, 일반적으로 아무런 이득도없이 만들 것입니다. – peoro
나는 동의한다 - 그러므로 나는 성능이 떨어질 것이라고 말했다. SafeInt를 사용하면 try-catch-block이 필요할 것이므로 아마도이 파일을 상당히 추가해야합니다. 그러나 문제는 오버 플로우를 감지하는 방법이었습니다.특정 경우에 대해서는 문제가 발생하지 않을 것이라는 점에 모두 동의한다고 생각하며 무시해야합니다. – Christoph
대신 xponentially-weighted moving average을 사용하는 것이 좋습니다. 이러한 접근법은 두 마리의 돌 하나를 죽일 것입니다. 많은 수의 누적 문제를 피할 것이며, 2010 년에 100fps의 누적 평균이 평균을 왜곡하지 않도록 2fps 속도 2011 년 한 달 정도 받아 들일 수있을 것 같습니다 :).
long int가 32 비트 인 경우 최대 값은 2^31-1이므로 1ms 업데이트의 경우 231 [2^31/1000/60/60/24]가 아닌 24.9 일에 오버플로됩니다.
OT ... 일반적으로 게임의 경우 이것은 실제로 문제가되지 않지만 다른 응용 프로그램을위한 것입니다. 일반적인 실수는
extern volatile uint32_t counter;
uint32_t one_second_elapsed = counter + 1000;
while (counter < one_second_elapsed) do_something();
만약 카운터 + 1000 오버 플로우와 같은 일을하고있다 조심 다음 호출되지 않습니다() do_something합니다.이를 확인하는 방법은 다음과 같습니다.
uint32_t start = counter;
while (counter - start < 1000) do_something();
작은 프레임 수에 대해 평균을 사용하는 것이 좋습니다. 당신은 평균을 계산하기를 원한다고 언급했지만, 평균을 계산하기 위해 그러한 많은 수의 샘플을 주변에 두는 이유는 없습니다. 단지 약간의 시간 (10-50 프레임 사이의 작은 크기 일 수 있습니다 - 우리는 일반적으로 16을 사용합니다) 동안 계속해서 전체 프레임 시간을 유지하십시오. 그런 다음이 합계를 사용하여 초당 평균 프레임 수를 계산할 수 있습니다. 이 방법은 또한 프레임 시간 보고서를 매끄럽게하여 숫자가 모든 곳으로 이동하지 않도록합니다. 한 가지주의해야 할 점은 너무 오랜 기간 동안 평균을 계산하면 프레임 속도가 급격히 높아지면서 프레임 속도가 떨어지게하는 프레임을 찾아내는 것이 더 어려울 수 있다는 것입니다. .
// current_frametime is the new frame time for this frame
Total_frametime -= Frametimes[Current_sample];
Total_frametime += current_frametime;
Frametimes[Current_sample] = current_frametime;
Current_sample = (Current_sample + 1) % Max_samples; // move to next element in array
Frames_per_second = Max_samples/Total_frametime;
: 당신이 당신의 프레임 - 타임을 계산할 때, 당신은 이런 일을 할 수있는 그런
// setup some variables once
const int Max_samples = 16; // keep at most 16 frametime samples
int FPS_Samples = 0;
int Current_sample = 0;
int Total_frametime = 0.0f;
float Frametimes[Max_samples];
for (int i = 0; i < Max_samples; i++) {
Frametimes[i] = 0.0f;
이 같은
뭔가 내가 (따르지 않는 테스트 코드를) 생각 완전히 충분하다 그것은 거친 상처이고 아마도 약간의 에러 검사를 사용할 수 있습니다, 그러나 그것은 일반적인 아이디어를 제공합니다.
왜 게임 전체에 평균이 필요합니까? 지난 몇 초/마지막 몇 초의 가치를 유지 한 다음 거기에서 귀찮게하지 않는 이유는 무엇입니까? –
long long long int와 같은 것을 사용할 수 없습니까? – BlackBear
@BlackBear 예, '긴 long int'가 있지만 동일한 문제에 대해 여전히 "잠재적"이 있습니다. –