ポーリングとイベント駆動入力


19

入力メソッドにポーリングを使用してゲームを開発しています。しかし、ゲームメニューやその他のUIコンポーネントをさらに深く掘り下げているので、おそらくイベントドリブンの入力が必要なことがわかりました。おそらく、UIにイベントドリブンを使用し、「world」入力をポーリングすることで、両方を持つこともできます。どうすればいいのか興味があります。

私はポーリングを次のように定義しています:更新ループごとに、どのキーが押されているか、マウスがどこにあるか、ボタンが押されているかを確認し、収集した情報に基づいてアクションを実行します。

イベント駆動型を定義しています:割り込みベースのイベント、イベントが発生し、割り込みがトリガーされ、イベントに基づいてコードブロックが実行される場合。

すべてのイベント駆動型、すべてのポーリングに行くのが最善だと思いますか、それとも両方の組み合わせが受け入れ可能ですか?どちらかの長所と短所がある場合は、それらをリストしてください。ありがとう。

編集

ゲームはJava / OpenGLベースであるため、Windows / Mac / Linuxにリリースされます。それをモバイルデバイスに拡張する可能性は低いです。ゲームはRTSスタイル、3人称3Dです。

編集2

私はこれを実装した方法にまだ完全に満足していませんが、私が向かっているのはUIでイベントをキャッチすることであり、イベントがUIコンポーネントのいずれかによって処理されない場合、イベントをピッキング/選択のための「世界」。何かのようなもの:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

この方法では、ボタンの背後にあるオブジェクトを選択するためにUIからクリックが漏れることはありません。

現在、私のカメラコントロールはまだポーリングに基づいており、今のところ機能しているようですが、後で更新する可能性があります。

すべての回答に感謝します。申し訳ありませんが、1つしか選択できません。


6
Javaには確信がありませんが、一般的には常に入力をポーリングする必要があります。その後、状況が変化したときにイベントをポストすることがありますが、これはまだポーリングシステムに基づいています。
ジェームズ

私の意見で最も重要な焦点は、入力コレクション以外のレイロードのないイベントループを設計することです。説明させてください:オペレーティングシステムは入力駆動の割り込みを行い、グローバルな「入力スレッド」でそれを処理し、このOSスレッドはメッセージを現在フォーカスのあるアプリケーションにリダイレクトし、Intelをメッセージキューに書き込みます。メッセージキューは、PeekMessageまたはGetMessageによってポーリングする必要があります。これを取得する最速の方法は、GetMessageを使用し、スケジューラーに起こさせることです。その後、メッセージに非常に正確にタイムスタンプを付けることができます。
v.oddou 14

回答:


17

ゲームとハードウェアの要件によって異なります。ほとんどのゲームは通常、入力状態の変更に関心があります。つまり、ユーザーが発射キーを押して武器の発砲を開始し、ユーザーが発射キーを放して武器の発射を停止し、移動キーを押して移動を開始し、移動キーを離して移動を停止しますなどです。そのため、イベント駆動型入力システムは、情報がすでに適切な形式になっているため、これらの場合に最も意味があります。さらに、Windowsプラットフォームでは、キーボードとマウスの状態を変更するイベントを既に受け取っているため、多くの場合、低レベルの入力イベントから高レベルのゲームイベントへの1:1変換です。ポーリングでは、現在のフレームと最後のフレームの状態を比較することにより、そのようなイベントを手動で生成しなければならないことがよくあります。基本的に、「現在どのボタンが押されていますか?」

とは言っても、特定のプラットフォームでは、低レベルでのポーリング入力にこだわるので、自分でエッジチェックを行う方法はありません。ただし、すべての高レベルロジックのイベントを使用することで、これらのシステムが動作する傾向があるのは当然のことなので、常に最高の結果を達成しています。


おかげで、私はゲームのプラットフォームと目的に関する追加情報を含めました。
マイケルハウス

1
これGetAsyncKeyStateは、Win32でポーリングを使用する簡単な方法です。
マッケ

デルプ、ネイトブロスのコメントで質問しましたが、ここで対処するので、私はそれを改良するつもりです。すべてのPCは、OSキーボードイベントとの関係に対して1:1のハードウェア割り込みを提供しますか。また、低レベルのポーリングに限定されるのはどのようなプラットフォームですか。
michael.bartnett

@Macke:アンチウィルスはこのAPIを使用するプログラムを報告することがあります。これは、グローバルシステム全体からキーを押すことができるため、悪意のあるキーロギングが可能になるためです。全体として、インターネット上でそれについての最も素晴らしい記事は、(私の知っている)、このいずれかになります。securelist.com/analysis/publications/36358/...
v.oddou

7

私はあなたが両方をすることができない理由を見つけません、そして、両方の世界の最高を得ます。

入力イベントはポーリングによって生成されます(あるレベルでは、ドライバーはハードウェアをポーリングしてその状態を確認します)。メインループはすべての入力デバイスをポーリングするため、独自のデバイスを簡単に実装できます。以下のような単純なものは、私が過去に使用したものです。

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

あなたはイベントを割り込みと定義し、ここに置いたものは「真のイベントベース」ではないことを知っていますが、割り込みがあなたに与えることを上記があなたに与えないことはわかりません-ほとんどのユーザーは気付かないでしょうゲームが非常に低いフレームレートで実行されない限り、単一のフレームが失われます。


1
デバイスから入力を取得する性質に興味があります。OSによってディスパッチされたキーボードイベントは、デバイスドライバーレベルでのポーリングの結果ですか?または、キーボードイベントは割り込みに対応していますか?または、割り込みがありますが、OSはそれらをバッファし、適切と判断したときにディスパッチしますか?
michael.bartnett

私はそのレベルでどのように機能するかについては肯定的ではありませんが、最も基本的なものです。一部のソフトウェアはループで実行され、キーボードの状態をチェックし、以前の状態と比較します(変更が変更された場合はバブルアップします)。
ネイト

5

ここには2つの異なる問題があります。

  1. OS /ハードウェアからユーザー入力をどのように読み取りますか?

  2. エンジンでユーザー入力をどのように処理しますか?

読むために、それは明らかにあなたのプラットフォームとあなたが読みたい入力の種類に依存します。入力レイヤーでは、あるものを別のものに簡単に変換できることに注意してください。(つまり、イベントをポーリングしてエンジンに送信するか、イベントをリッスンしてエンジンに状態を送信します。)

処理には、いくつかの異なるオプションがあります。

  • プレーヤーの移動制御(および同様のスキーム)の場合、各フレームの速度を再計算する必要があるため、ポーリングはより簡単になる場合があります。内部ループがポーリングベースになる可能性が非常に高くなります。

    すなわちのようなもの speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • 個別のイベント(ミサイルの発射、ゲームの一時停止、惑星の反対側へのテレポート)の場合、イベント処理の方がmaybeLaunchMissile(key_state);望ましいです。;)

それが役に立てば幸い。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.