画面上のマウス位置を「マッピング」して、解像度に関係なく衝突検出が機能するようにするのは悪い考えですか?


16

デフォルトの解像度が800x600のゲームを考えてみましょう。衝突マスクを持つオブジェクトは、サイズ800x600のゲームワールドに配置されます。衝突マスクは、マウスが衝突マスクに衝突したことを検出できます。

次に、ゲームを1024x768に拡大することを考えます(すべてをレイヤーにレンダリングし、レイヤー全体を一度に拡大するだけでグラフィックを拡大すると仮定します)。この新しい解像度でマウスとの衝突を適切に機能させるには、2つのオプションがあります。

A.)ワールドを1024x768に拡大し、それに応じてすべてのオブジェクトのコリジョンマスクを拡大します。

B.)マウスの位置を元の世界(800x600)に「マッピング」します。

「マップ」とは、マウスの位置を元の800x600の世界に単純に拡大縮小することを意味します。たとえば、画面上のマウス位置が(1024、768)の場合、世界のマウス位置は(800、600)です。

明らかに、オプションBのが計算量が少なく、おそらく幾何学的エラーが発生しにくいかもしれませんが、このメソッドを使用すると予期せぬ結果が生じるため、後で修正する必要があります。

どちらの方法を使用する必要があります:A、B、または他の何か?


2
Classic Thunderが指摘したように、ディスプレイの座標は、ワールド座標またはオブジェクト座標と同じであってはなりません。通常、変換が必要です(基本的に、mappingsと言いますが、通常は行列演算で行います)。
ダン

回答:


38

通常(2Dゲームの場合でも)、解像度に依存しないゲーム用の独立した座標系があります。これは通常、ワールド空間と呼ばれます。これにより、任意の解像度にスケーリングできます。

これを実現する最も簡単な方法は、2Dカメラを使用することです。2Dカメラは、本質的に、ワールド空間(任意の単位)から画面空間(画面上のピクセル)への遷移を定義するマトリックスです。これにより、数学の扱いが簡単になります。

XNA 2dカメラスクロールの以下のセクションをご覧ください-マトリックス変換を使用する理由

座標系定義間の変換が非常に簡単になります

画面からワールドスペースに移動するには、Vector2.Transformを使用します。これは一般的に、オブジェクトを選択するためにワールド内のマウスの位置を取得するために使用されます。

Vector2.Transform(mouseLocation, Matrix.Invert(Camera.TransformMatrix));

世界からスクリーン空間に行くには、単に反対を行います。

Vector2.Transform(mouseLocation, Camera.TransformMatrix);

マトリックスを使用することには、多少の学習が必要になること以外に欠点はありません。


...そして実際、一般的に言えば、現代のハードウェアはSSE、NEONなどのベクトル化アーキテクチャを介した行列演算用に設計されています。したがって、賢明な選択です。ベクトル化されていないアプローチよりもCPUサイクルを節約できます。
エンジニア

1
軽度の免責事項:XNAはマイクロソフトによって廃止されましたが、Monogameは同じAPIを使用しています。
ファラプ

1
もちろん、マトリックスを使用して2つの座標系間を変換するのが賢明です。しかし、それは質問にどのように答えますか?システムAからシステムBにマップするか、BからAにマップするか、および結果がある場合はそれを決定する必要があります。
マストフ

「衝突の検出が解像度に関係なく機能するように、画面上のマウス位置を「マッピング」するのは悪い考えですか?」「マトリックスを使用して2つの座標系間を変換するのが賢明です」と回答されました
...-ClassicThunder

また、「システムAからシステムBにマップするか、BからAにマップするか、および結果があれば、それを決定する必要があります」と答えます。あなたはそれから解像度とスケールに縛られていない任意のものを使うべきだと言って。したがって、AまたはBが解像度であるかどうかに応じて、C-> AまたはC-> Bになります。もちろん、Cを設計の基本解像度に等しくし、そこからスケーリングすることができます。ポイントは、すべての数学が同じ座標系で発生し、レンダリングのためにスケーリングするだけです。
ClassicThunder

2

別のオプションは次のとおりです。各入力マウス移動イベントで、マウスイベントのピクセル数に対応するゲームピクセル数だけゲーム内マウスカーソルを移動します。これは、実際のマウスポインターを中心にロックし、入力マウスの動きに対応する量だけ照準方向を回転させる3Dゲームでは自然に発生しますが、ゲーム内のマウスカーソルを表すスプライトを移動することでも同じようにできます。

明らかに、中心への反りによって引き起こされる入力マウスの移動イベントを無視する必要があります。ゲームですべてのカーソルに入力ラグがある場合、無応答性が最も不快で目立つ側面になります。

部分的に、どのソリューションを使用するかは、ゲームプレイにとってマウスの位置がどれだけ重要かによって異なります。これがRTSであり、プレイヤーが単にユニットをクリックして選択している場合、おそらくAまたはBのどちらかが簡単な方に行くことができます。トップダウンシューターで、マウスがキャラクターの動きを直接制御する場合、解像度だけでなくマウスの動きなどに基づいてキャラクターがどのように動くことができるかについてのばらつきの量を制限する、より詳細なソリューションが必要になるでしょう。速度。代わりにマウスがターゲットの方向を制御する場合、別のソリューションなどが必要になります。


0

ClassicThunderの答えは正しいですが、望ましい効果を達成するための代替/より簡単な手段の例を提供したいと思います。これは、ラピッドプロトタイピング、フル機能のライブラリにアクセスできない場合、またはGPUにアクセスできない場合(組み込みシステムなど)のよりシンプルなソリューションです。

このマッピングを実行するには、次の関数を使用できます(静的クラスで定義されていると仮定しますHelper)。

static float Map(float value, float fromLow, float fromHigh, float toLow, float toHigh)
{
    return ((value - fromLow) / (fromHigh - fromLow) * (toHigh - toLow)) + toLow;
}

(言語は指定しませんでしたが、C#の知識があるので、私の例はC#です。)

この関数は次のように使用できます。

float mouseXInWorld = Helper.Map(Mouse.X, 0, Screen.Width - 1, camera.Bounds.X, camera.Bounds.X + camera.Bounds.Width - 1);
float mouseYInWorld = Helper.Map(Mouse.Y, 0, Screen.Height - 1, camera.Bounds.Y, camera.Bounds.Y + camera.Bounds.Height - 1);

camera.Boundsカメラが見ることができる世界の領域(つまり、スクリーンに投影される領域)を表す長方形はどこにありますか。

VectorまたはPointクラスがある場合、次のようにmap関数と同等の2Dを作成することにより、このプロセスをさらに簡素化できます。

static Vector Map(Vector value, Rectangle fromArea, Rectangle toArea)
{
    Vector result = new Vector();
    result.X = Map(value.X, fromArea.X, fromArea.X + fromArea.Width - 1, toArea.X, toArea.X + toArea.Width - 1);
    result.Y = Map(value.Y, fromArea.Y, fromArea.Y + fromArea.Height - 1, toArea.Y, toArea.Y + toArea.Height - 1);
    return result;
}

これにより、マッピングコードは単純な1つのライナーになります。

Vector mousePosInWorld = Map(Mouse.Pos, Screen.Bounds, camera.Bounds);

-1

オプション(C):画面の解像度を800x600に戻します。

これを行わなくても、思考実験と見なしてください。その場合、グラフィックのサイズを物理的なサイズに合わせて変更するのはディスプレイの責任であり、800x600の解像度でポインタイベントを提供するのはオペレーティングシステムの責任です。

グラフィックスがビットマップかベクターかによってすべてが決まると思います。ビットマップで、800x600のバッファーにレンダリングする場合、はい、マウスを画面スペースに再マップし、実際の画面解像度を無視する方がはるかに簡単です。ただし、これの大きな欠点は、特にブロック状の「8ビット」スタイルのグラフィックスを実行している場合、アップスケーリングがいように見えることです。

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