2009-03-25 10 views
6

すべてのゲームチュートリアルとゲームフレームワーク(新しいXNAフレームワークでさえ)は、DoEvents()に相当する無限ループから始まり、OSがロックされないようにします。無限ループ+ブロックよりも優れたゲームループですか?

ゲーム以外の観点からのコミットメント私は、この種のコードがかなりファンキーな臭いを感じています。
代替手段はありませんか?

--EDIT--
回答の多くは、すべてのプログラムは基本的にループであると言います。本当ですが、あなたのOSではなく、あなたのループが実行されるべきだと感じています。 OSだけが、リソースを最適な方法で配布するために必要なすべての情報を持っています。あるいは、私はここで重要な点を見逃していますか?

+0

ええ、ゲームがOSサービスではないという重要な違いはありません。 – Hejazzman

答えて

5

すべてのWindowsアプリケーションは、その中核に、このようになりますループを持っています

BOOL bRet; 

while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) 
{ 
    if (bRet == -1) 
    { 
     // handle the error and possibly exit 
    } 
    else 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

それはアプリケーションの仕事です - いないオペレーティングsystem's - メッセージがディスパッチされることを保証するために。

初期のWindowsゲームでは、ブロックGetMessageの機能を呼び出す代わりにPeekMessageを呼び出し、処理するメッセージがなければゲームのメイン処理ループを呼び出す別の方法が使用されていました。 100%CPUを使用せずに適切なフレームレートを得るために、さまざまな形式の遅延が使用されていました。滑らかなフレームレートを与えるのに十分なタイマーがなかっただけです。

今日では、DoEventsを呼び出すループを明示的に記述する必要はありません。現在、によって.NETに公開され、System.Timers.Timerでラップされた組み込みタイマープールタイマーを使用してスムーズなフレームレートを得るために、になる可能性があります。

思い出したように、タイムリーにマウスイベントやキーボードイベントを取得する問題もありました。メッセージループは遅すぎることが多く、情報を失うことがあるため、メッセージループに依存するのではなく、直接キーボードとマウスのアクセスを使用しました。

私は何年もの間ゲームを書いていませんし、.NETがゲームプラットフォームのようなものかどうかはわかりません。入力がまだ問題である可能性があります。つまり、メッセージキューは、ゲーム開発者が望むような俊敏な応答を与えるだけの速度ではありません。したがって、重要な作業のためにメッセージキューをバイパスします。

私はgamelogicダニを呼び出すためにマルチメディアタイマを使用Win32で
+0

フレームを作るためにスクリーンの周波数を知っているタイマーを作ることができたら、私は実際に考えていました。そうしたやり方で不必要な走りが生まれました。 @ブライアン・パーカー(Bryan Parker)のアイデアは、残りの部分(ゲームロジック/ IO)から引き離すために別のスレッドに描画することもあります。 –

+0

..いいアイデアのようです。私はそれがpraticalかどうかわからない。 –

+1

ほとんどのゲームは別のスレッドでレンダリングしています。また、パフォーマンスのテストのためにvsyncからデカップリングできるようにしたい(その他の理由の中でも) – BigSandwich

1

実行中のすべてのプログラムは決してループを終了しません。場合によっては、ループ(ウェブプログラミングや他のマイナープログラムなど)とやり取りしない場合もありますが、

OSは入力コマンドを待っているループです。ゲームと同じです。 Webサーバーは要求を待つループです。

偉大説明ユーザからであるslim on one of my own questions.

+0

あなたは基本的に正しいですが、これはGUIベースのプログラムにのみ当てはまります。簡単なコマンドラインアプリケーションでは、メインループなしで簡単に手に入れることができます。 –

+0

説明を追加しました。 –

+0

あなたの記事を読んで、実際に私はそれを考え出した。しかし、OSは既にこのループを実行しているので、OSループ内に独自のループを作成するのではなく、そのループにフックする(OSのイベントを使用する)のは良い考えではありませんか? –

0

メッセージキューは無限ループなど、すべてのプログラムを作るだけでなく、無限ループです。

-3

あなたはそれについて快適に感じていない場合は、クラスやインタフェースを持つ パッケージを、

私たちは「オープンとクローズの原則」と言うものです

:変更されたことがないインターフェースを開く 、汚れた部分を閉じます。

なぜループを使用しますか?それは私たちのコンピュータの基本的な構造ですから!

+0

私は誤ったコミュニケーションがあることを恐れます。私は醜いビットを隠す方法を知っていますが、問題はなぜOSループ内にループを実装するべきかということです。 –

1

より良いループは、イベント/メッセージのディスパッチをブロックする無限ループです。何もする必要がなければ、実際にはスリープ状態にはならず、OSを待つ間にブロックする必要があります。しかし、イベントをポーリングするときにOSが実際にブロックしない場合は、CPU使用率を100%に抑えるためにポーリングとスリープの唯一の方法があります。

+0

それは、実際には私が睡眠を意味するものです。 (古いDoEvents)。それを反映するように投稿を変更します。 –

1

どうやってどうやって違うのでしょうか?

あなたのプログラムはスレッド内で実行されます(空想的な場合は複数のスレッドが実行されます)。 gameloop(またはWin32 GetMessage/DispatchMessageポンプ)を持つことは、イベントの発生を待ってからそれらを処理することです。代わりにコールバックを登録してから、内部的にはほとんど同じことを行うHandleAllMyMessages()を呼び出すことになります。それはあなたに何も買わないでしょう。

OSは、スレッド内で何をしたいのか分からないため、プログラムを複数のスレッドに魔法のように分割することはできません。すべての着信メッセージに対して新しいスレッドを生成することは、パフォーマンスと同期の両方の地獄になります。

1

...

// request 1ms period for timer 
g_mmTimer = timeBeginPeriod(1); 
if (g_mmTimer != TIMERR_NOERROR) 
    return false; 

//start game loop event timer/thread 
g_mmTimer = timeSetEvent(10, 10, DoUpdate, 0, TIME_PERIODIC); 

必要に応じてゲームロジックは、フレームレートを自動的に独立であるように、あなたは別のスレッドですべての描画を行うことができます。

2

ゲーム(ほとんどの場合)はシミュレーションです。伝統的にこれは、シミュレーションを更新し、現在の状態(例えば、グラフィックスをレンダリング)を提示し、繰り返すことを意味します。これに対する自然な表現はループです。

一方、Win32メッセージポンプは、Windows上の大多数のアプリケーションを構成するイベントドリブンのアプリケーション向けのプラットフォーム固有のクワークです。これは決してすべてのプラットフォームのアプリケーションの標準ではないので、すべてのソフトウェアがモデルにうまく収まるとは限りません。したがって、典型的なプログラムをWin32モデルに合わせて修正するには、ループが繰り返されるたびにPeekMessageが空になるまでそのキューを一度に流出させます。または、そのロジックを別のスレッドに入れ、適切なGetMessageを使用します。

パフォーマンスを考慮したほとんどのゲームでは、これを行うための他の実際の方法はありません。第1に、ポーリングではなくイベントを駆動するようにしようとすると、多くのゲームで高いパフォーマンスを維持したい場合、Windowsが確実に提供できるよりも高い解像度のタイミングが必要になります。第2に、Windowsはゲームが書かれているプラ​​ットフォームの1つに過ぎず、Win32モデルにうまく収まるようにゲームを改造することは、代わりに正規のゲームループを期待する専用のゲームプラットフォームにとっては不便です。

最後に、「100%CPUをとる」という心配は間違っています。最新のゲームのほとんどは、専用ハードウェアアクセスでフルスクリーンモードで使用するように設計されており、いくつかの他のアプリケーションが共存するものではありません。このようなゲームの顧客は、実際にはゲームがハードウェアを最大限に活用することを要求しています。スリープ()の意図的な呼び出しや更新がアプリケーションを毎秒N回起動する外部タイマーに依存している場合は、明らかに、多くのゲームの例外があります。主にウィンドウで実行するように設計されているものですが、その区別に注意することが重要です。

+0

ファンタスティックな回答と概要。 –

+0

CPUを100%使用することは、確かに有効な懸念事項であり、避けるべきことです。フルスクリーンのフォアグラウンドでも、CPUサイクルを無駄にすることはありません。それは、一年ごとにますますパワーマネージメントを妨げています。あなたがあなたの答えを書いたときには、それはラップトップにとって懸念されていただけです(それでもCPUを焼くほどの理由はありません)。今日では、CPUコアをTurbo Boostに追い込み、統合されたGPUで使用可能な電力を削減します。だからあなたのゲームのためのすべてのリソースを掘り起こすあなたの考えは、実際にそのパフォーマンスを低下させます。 -1 –

+0

@BenVoigt - これは有効な点ですが、ターゲットとするプラットフォームによって異なります。モバイルまたはラップトッププラットフォーム専用のものではないAAAゲームは、何らかの理由で故意にスリープサイクルを導入しないで、使用可能なCPUリソースを埋めるために処理をスケールアップします。さらに重要なことは、統合されたGPUで優れたパフォーマンスを発揮することは期待されないことです。ゲームソフトに関する限り、第二級の市民です。しかし、あなたがモバイルを目指しているなら...それは別の話です。 – Kylotan

0

MsgWaitForMultipleEventsは、WaitableTimerのように、タイムアウトとカーネルオブジェクトを待機する機能を組み合わせたものです(GetMessage/PeekMessage)。

私はMsgWaitForMultipleEventsと一緒に希望のフレームレートを設定して、忙しい待たずに過去に非常にスムーズなアニメーションを成功させることができました。私は他のOSがとてもいいと思っています。

関連する問題