2011-01-13 18 views
3

タイトルはあまりよくありませんが、名前を知ることはできませんでした。C++:ゲームの合計フレーム数を計算する

とにかく、私はlong intでゲームの合計フレーム数を計算しています(私は平均FPSを計算できます)。試合が本当に長く続くような場合には、私のlong intが限界を超えて増加しないようにするために何をすべきですか?それが限界を過ぎてしまったらどうなりますか?

ありがとうございました。

+1

なぜゲーム全体に平均が必要ですか?最後の2秒間/最後の数秒間のカウントを維持し、そこから気にしないのはなぜですか? –

+0

long long long intのようなものを使用することはできませんか? – BlackBear

+0

@BlackBearはい、 'long long int'がありますが、同じ問題の「潜在的可能性」はまだあります。 –

答えて

4

ゲーム全体の平均FPSは、非常に有用な統計ではないようです。通常は、最高fps /最低fpsや、しきい値を下回る、上回るフレームの量など、ピークと谷を測定することをお勧めします。

実際には、私は心配しません。 32ビットの符号なし整数を使用するだけであっても、オーバーフローする前に19884時間60fpsでゲームを実行することができます。あなたは大丈夫です。

EDIT:この場合、オーバーフローを検出する

最良の方法は、チェックと整数がインクリメントされた後の値で減少かどうかを確認することです。そうであれば、あふれた回数だけ別のカウンタを保持することができます。

8

この問題は、あらゆる種類のカウンタで発生します。

あなたの特定の問題については、私は心配しません。

long intは、最悪の場合(32ビットコンピュータ/コンソールの場合)には最大数十億(最大)をカウントします。あなたのゲームが毎秒1000フレーム(これは大変です!)を行っていると仮定すると、カウンタのオーバーフローには20000000秒かかります.1000時間以上、231日以上です。

私はかなり長い間それを実行しようとすると、あなたのゲームが停止する原因になると確信しています!

+1

ショートゲームの種類があります。 –

+0

@peoroはい、私は自分で計算しましたが、これはちょうどその時です。カウンターが過度に増加するとどうなりますか? –

+0

@Jay:署名されていないと宣言されている場合は0に戻ります。そうでない場合は負の数になります。これの正確な効果はコードに依存します。 – luiscubal

1

算術演算のオーバーフローを積極的にチェックできます。 E. SafeIntはそれを行うことができます。もちろん、パフォーマンスはi++よりも悪いです。

しかし、常に1ずつ増分すると、32ビット整数がオーバーフローすることは考えられません。

+0

私はこのような場合にこのようなことは提案しません。オーバーフローを避けるための他の解決法は、より長い型を使用して値を格納することです。いくつかの高度な数学ライブラリによって提供される 'long long'または動的長さの整数さえあります。しかし、この場合、それはそれに値するものではなく、物事を遅くし、複雑にし、一般的には何の利益ももたらさない。 – peoro

+0

私は同意する - したがって、パフォーマンスが低下すると言いました。 SafeIntを使用するとtry-catch-blockが必要になるため、おそらく私はそれを大幅に低下させるでしょう。しかし、問題はオーバーフローを検出する方法でした。具体的なケースでは、問題は起こりそうもないと私たちは皆同意したと思います。あなたは無視してください。 – Christoph

5

代わりに、私はxponentially-weighted moving averageを使用することを考えます。このアプローチでは2羽の鳥が1つの石で殺されます。それは多数の累積の問題を回避し、2010年の100fpsの累積平均で平均を歪ませないように最近の動きにも適応し、2fpsのレート2011年には1ヶ月程度は受け入れられるようです:)。

1

long intが32ビットの場合、最大値は2^31-1なので、1msの更新では、231 [2^31/1000/60/60/24]ではなく24.9日でオーバーフローします。

OT ...一般的にゲームの場合は、実際には問題ではないかもしれませんが、他のアプリケーション用です。 do_somethingその後、

extern volatile uint32_t counter; 
uint32_t one_second_elapsed = counter + 1000; 
while (counter < one_second_elapsed) do_something(); 

カウンタ+ 1000年であればオーバーフローのようなものをやっているのに注意するよくある間違いは、()が呼び出されることはありません。これを確認する方法は、

uint32_t start = counter; 
while (counter - start < 1000) do_something(); 
0

少数のフレームにわたって平均を使用する方が良いでしょう。あなたは平均を計算したいと言いましたが、平均を計算するためにそのような数のサンプルを周りに保つ理由は本当にありません。ちょっとした時間(10〜50フレームの間のものがありますが、通常は16を使用します)の間に、フレームタイムの連続した合計を維持してください。その合計を使用して、毎秒の平均フレームを計算することができます。この方法はまた、フレーム時間レポートをスムーズにして、数字がその場所のどこにも飛ばないようにします。 1つのことは注意しなければならないのは、あまりにも長い時間平均した場合、フレームレートのスパイクがより「隠れた」ようになり、フレームが非常に頻繁にしか発生しない場合にフレームレートを低下させるフレームを見つけることが難しくなる。

// 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; 

:あなたの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; 

:このような

何かが、私は(フォローする非テストコード)を考えて、完全に十分であろうそれは大まかなカットで、おそらく何らかのエラーチェックを使うことができますが、それは一般的な考え方を示しています。