C#/ XNAハードウェアマウスの位置を取得


10

私はC#を使用していて、ハードウェアマウスの位置を取得しようとしています。最初に試したのは、使いやすいシンプルなXNA機能です。

Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

その後、マウスの描画も行い、Windowsハードウェアマウスと比較して、xnaが提供する座標を持つこの新しいマウスは「ずれ」ています。つまり、数フレーム遅れているということです。たとえば、ゲームが600 fpsで実行されている場合、呪いは反応しますが、60 fpsのソフトウェアではマウスの遅延は許容できなくなります。そこで、ハードウェアマウスだと思ったものを使ってみました。

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);

しかし、結果はまったく同じでした。私はまた、Windowsフォームカーソルを取得しようとしましたが、これも行き止まりでした-動作しましたが、同じ遅延がありました。xna機能をいじくりまわす:

GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale

やや明白な理由で遅延時間を変更しましたが、肝心な点は、それがデフォルトのWindowsマウスの背後にあるにもかかわらずです。一部のゲームでは、ハードウェアアクセラレートマウスのオプションが提供されていることがわかりました。誰でもそれを達成する方法についていくつかのリードを与えることができますか?


2
Mouse.GetState()壊れているとは思いません。描画しているのと同じフレームでマウスの位置を取得していますか?また、Windowsカーソルでは加速/減速が有効になっているので、応答性高くなります。ハードウェアに近づきたい場合は、DirectInputを押してください。これにより、マウスの絶対位置ではなく、動きのデルタが得られます。しかし、私はMouse.GetState()XNAでそれを行う正しい方法がまだあると信じています。
パンダパジャマ

いいえ、Mouse.GetState()壊れていませんIsFixedTimeStep == true。可視ウィンドウマウスと直接比較しない限り、遅延を確認できないはずです。ただし、低いフレームレートでIsFixedTimeStepをfalseに設定すると、すべての人に表示されます。直接入力については可能性(最後の手段)と考えました。
サンダー

それが必要なものかどうかはわかりませんが、ウィンドウ内にあるときにカーソルスプライトを変更して、常に表示されるようにするにはどうすればよいでしょうか。
William Mariager

それはまさに私がやっていることです、それは私がそれを示すだけではなく、マウスの正確な位置も知りたいということです。しかし、私が得ているものは、本来あるべきものに対して少し遅れています。
サンダー

回答:


16

あなたが見ているの入力の遅れではありません

Windowsでカーソルの位置を取得するには、WM_MOUSEMOVEまたはを使用できますGetCursorPos。どちらも、Windowsが処理した後のカーソルの位置を提供し、加速などを適用します。これは、描画を含むWindowsが使用するカーソル位置です。そしてほとんど常にあなたが使いたいものも。

これはXNAが使用するものです。具体的にはGetCursorPosMSDN)。これは、を呼び出すとMouse.GetState、Windowsが認識するカーソルの実際の位置を取得することを意味します-実質的に遅延はありません。

これで、WM_INPUT(または非推奨ですがDirectInput)を使用できます。これにより、生のポインタデータが得られます。これは、Windowsがアクセラレーションなどを適用できるようになる前のことであり、通常必要ありません。

表示されているの出力ラグです。

これは「ハードウェアカーソル」が原因です。これは、GPUでのことで、画面上に描画されます小さなスプライトです非常にそのパイプラインの終わり。そして終わりを意味します。これはフレームバッファーの後にあります。画像がモニターに送信されるときにデータストリームに挿入されます。それが非常に迅速に反応する理由は、GPUレジスタを直接設定することによってその位置が設定されるためです。パイプラインでの待機はまったくありません。

一方、ゲームはGPUパイプラインを経由する必要があります。これにより、多くの遅延が発生します。これらの中で最も問題となるのは、ダブルバッファリングです。これはXNA 4ではオフにできません(かなり確信しています)。フレームバッファーに直接描画するのではなく、バックバッファーに描画します。(60FPSで)〜16msごとに表示されます。つまり、Mouse.GetState画面上でその結果に基づいて何かを取得した結果を受信するまでに最低約16msを見ていることになります。おそらくもっと長い。確かに、ハードウェアカーソルよりもかなり低速です。

それで、解決策は何ですか?

1つは、SetCursorMSDN)を使用して、ハードウェアカーソルによって表示される画像を変更し、ゲームにより適した画像にする(またはWindowsカーソルと共に使用する)ことです。

そしてもう1つ(はるかに簡単)は、ラグを受け入れるだけでGame.IsMouseVisible = false、相対的なラグを隠すように設定することです。ゲーム内に自分のカーソルを表示します。非表示のWindowsカーソルよりも16ミリ秒遅くなりますが、誰が気にしますか?ゲーマーはそれに慣れています。とにかく16msはほとんど視覚的に感知できません(それが60FPSでレンダリングする理由です)。


詳しい説明ありがとうございます。ほとんどの場合、私はXNAマウスを使い続けます。誰かに追加の回避策がある場合に備えて、受け入れる前に少し待つ予定です。
2012

ラグを受け入れるかどうかは、プレイテストで答えるべき問題だと思います。
Zonko
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.