web-dev-qa-db-ja.com

SDL_PollEventとSDL_WaitEvent

だから私は「SDLでのマルチスレッドプログラミングのヒントとアドバイス」を含むこの記事を読んでいました--- https://vilimpoc.org/research/portmonitorg/sdl-tips-and-tricks.html

SDL_PollEventは、過剰なCPU使用率を引き起こす可能性があるため非効率的であると説明しているため、代わりにSDL_WaitEventを使用することをお勧めします。

両方のループの例を示していますが、これがゲームループでどのように機能するかはわかりません。 SDL_WaitEventは、定期的な更新を必要としないものによってのみ使用する必要がある場合があります。つまり、ゲームを実行している場合は、フレームごとにゲームロジックを実行します。

私がそれを使用できると思う唯一のものは、ユーザー入力に必要なアクションだけがあるペイントプログラムのようなプログラムです。

一般的なゲームプログラミングにSDL_PollEventを引き続き使用する必要があると考えるのは正しいですか?

20
Zammalad

ゲームがユーザー入力でのみ更新/再描画する場合は、SDL_WaitEventを使用できます。ただし、ほとんどのゲームでは、ユーザー入力がない場合でもアニメーション/物理演算が実行されます。したがって、SDL_PollEventはほとんどのゲームに最適だと思います。

SDL_WaitEventが役立つ可能性がある1つのケースは、SDL_WaitEventが1つのスレッドにあり、アニメーション/ロジックが別のスレッドにある場合です。そうすれば、SDL_WaitEventが長時間待機していても、ゲームはペイント/更新を続行します。 (編集:これは実際には機能しない可能性があります。以下のHenrikのコメントを参照してください)

記事に示されているように100%CPUを使用するSDL_PollEventについては、ゲームが必要な1秒あたりのフレーム数を超えて実行されていることを検出したときにループにスリープを追加することで、これを軽減できます。

11
priomsrb

入力にサブフレームの精度が必要なく、ゲームが常にアニメーション化されている場合は、SDL_PollEventが適切です。

サブフレームの精度は、たとえば次の場合に重要になる可能性があります。プレーヤーが動きの非常に小さな増分を必要とする可能性があるゲーム-キーダウンの古典的な怠惰な方法を使用して「速度= 1」を意味し、キーアップを「速度= 0」を意味する場合、キーをすばやくタップして離すと、予測できない動作が発生します。フレームごとに1回位置を更新します。タップがフレームレンダリングと重なっている場合は、1フレームの移動時間が得られます。そうでない場合は、移動がありません。実際に必要なのはは、イベントが発生したタイムスタンプに基づくフレームの長さよりも小さい移動量です。

残念ながら、SDLのイベントには、オペレーティングシステムからの実際のイベントのタイムスタンプは含まれず、PumpEvents呼び出しのタイムスタンプのみが含まれ、WaitEventは10ミリ秒間隔で効果的にポーリングするため、WaitEventが別のスレッドで実行されている場合でも、最も高い精度が得られます。 10ms(同じポーリングサイクルでキーダウンとキーアップを取得した場合、約5msになると言うことで、概算で小さくすることができます)。

したがって、入力に正確なタイミングが本当に必要な場合は、実際には、より小さなSDL_Delayを使用して独自のバージョンのSDL_WaitEventTimeoutを記述し、thatを実行する必要があります。メインのゲームループからスレッドを分離します。

さらに残念ながら、SDL_PumpEventsは、ビデオサブシステムを初期化したスレッドで実行する必要があります( https://wiki.libsdl.org/SDL_PumpEvents ごと)。したがって、別のスレッドで入力ループを実行するという全体的なアイデアは、サブフレームの取得のタイミングは、SDLフレームワークによって決まります。

結論として、アニメーションを使用するSDLアプリケーションの場合、SDL_PollEvents以外のものを使用する理由はありません。サブフレームレートの入力精度のためにできる最善のことは、フレームを書き込む時間があれば、その時間中に正確にするオプションがあります。 、しかし、その後、入力の精度が失われるフレームごとに奇妙なレンダリング期間ウィンドウが表示されるため、異なる種類の不整合が発生します。

7
Raven Black

一般に、SDL_PollEventではなくSDL_WaitEventを使用して、CPUをオペレーティングシステムに解放し、ユーザー入力の処理などの他のタスクを処理する必要があります。これは、ユーザーがコマンドを入力してからアプリケーションがイベントを処理するまでの間に遅延を引き起こす可能性があるため、ユーザー入力に対する反応が遅いことをユーザーに示します。代わりにSDL_WaitEventを使用することで、OSはアプリケーションにイベントをより迅速に投稿できるため、知覚されるパフォーマンスが向上します。

副次的な利点として、ラップトップやポータブルデバイスなどのバッテリー駆動システムのユーザーは、ゲームが100%の時間使用していないため、OSが全体的なCPU使用率を削減する機会があるため、バッテリー使用量がわずかに少なくなるはずです。イベントが実際に発生したときに使用します。

5
Darius Makaitis

実際にメインスレッドでSDLとウィンドウを初期化し、更新(時間の経過とともにゲームの状態と変数を更新するだけ)とレンダリング(それに応じてサーフェスをレンダリングする)のためにさらに2つのスレッドを作成できます。それがすべて終わったら、メインスレッドでSDL_WaitEventを使用してSDL_Eventsを管理します。このようにして、sdl_initを呼び出したのと同じスレッドでイベントが管理されるようにすることができます。

私はこの方法を長い間使用して、ゲームをWindowsとLinuxで動作させ、上記のように3つのスレッドを同時に正常に実行することができました。

ミューテックスを使用して、レンダリングスレッドを一時停止することで、更新スレッドでもテクスチャ/サーフェスを変換/変更できるようにする必要がありました。ロックは60フレームごとに呼び出されるため、パフォーマンスに大きな問題は発生しません。

このモデルは、イベント駆動型ゲーム、ランタイムゲーム、またはその両方を作成するのに最適です。

0
Anantha