XNA を使用した単純な 2D リアルタイム戦略ゲームに取り組んでいます。現在、ユニットまたは建物のスプライトをクリックして、そのスプライトに関連付けられたオブジェクトを参照できるようにする必要があるところまで来ました。過去 3 日間に行った調査から、3D で「マウス ピッキング」を行う方法について、私の状況には当てはまらないと思われる多くの参考文献を見つけました。これを行う別の方法は、単にワールド内のすべての「選択可能な」オブジェクトの配列を持ち、プレイヤーがスプライトをクリックすると、配列内のすべてのオブジェクトの位置に対してマウスの位置をチェックすることだと理解しています。このアプローチで私が抱えている問題は、ユニットと建物の数が増えるとかなり遅くなるということです。(それもあまりエレガントではないようです)それで、これを行うことができる他の方法は何ですか。(ハッシュ テーブルを使用してオブジェクトをスプライトの位置に関連付け、配列内の各位置が世界の 1 つのピクセルを表す 2 次元配列を使用するというアイデアについても検討したことに注意してください。物事を行う不格好な方法。)
3 に答える
最大数百のユニットの場合、クリック領域が円または長方形の場合、世界中のすべてのユニットに対して単純に線形検索 O(n) を実行するのに十分な速さである必要があります。特に、フレームごとではなく、クリックごとに 1 回になることを確認してください。
ユニットが円形または長方形でない場合は、最初に境界の円または長方形をチェックし、それが合格した場合は、より複雑な境界形状をチェックします。
より詳細な回答については、スペースの分割に関する同様の質問に対する私の回答をご覧ください。そこでは、パフォーマンスを最適化するための潜在的な構造として、バケット化されたグリッドと四分木について言及しています。
ただし、テストして実際にパフォーマンスの問題が発生するまでは、パフォーマンスの最適化を行うべきではありません。
drawabelオブジェクトを管理するクラスがある場合は、新しいオブジェクトを作成するたびに増加する静的intを作成し、古いオブジェクトをColorのローカルインスタンスとしてdrawabelオブジェクトに保存できます。次に、.Netタイプのコンバーターを使用して、配列を並べ替えて元に戻すことができます。電車の中で名前と電話番号を覚えていないので、恐れて確認することはできません。
バイト配列から色を作成するときは、アルファチャネルを最大化することを忘れないでください。オブジェクトが多すぎると、使用できるインデックスがオーバーランする可能性があります。次に何をすべきかわからない...おそらくすべてのオブジェクトがあります。うまくいけば、いくつかの古い色がもう使用されていないので、0:0:0:255から新しい色を再度必要とします:P
私が多くの意味を成したかどうかはわかりませんが、電車に乗っているので、私があなたに与えることができるのはそれだけです、ごめんなさい:)
ピクセル パーフェクト ピッキングを使用できます。これは、膨大な数のオブジェクトに非常によく対応します (また、ピクセル パーフェクトであるという利点があります)。
基本的に、オブジェクトごとに固有の色を使用してシーンをレンダリングします。次に、バックバッファをテクスチャに解決し、テクスチャ データを取得します。最後に、マウスの下のピクセルをチェックして、マウスが置かれているオブジェクトを見つけることができます。
返される情報について賢くすることができます。マウスが上にある単一のピクセルだけを要求することができます。
Color[] pixel = new Color[1];
texture.GetData(pixel, mousePosition.Y * texture.Width + mousePosition.x, 1);
//pixel[0] == colour of the item the mouse is over. You can now look this up in a dictionary<Color, item>
これを行ってパイプラインを失速させないように注意する必要があります (CPU が GPU によるレンダリングを待機する原因になります)。これを行う最善の方法は、2 つのレンダー ターゲット間で交換し、常に前のフレームで使用したレンダー ターゲットから GetData を取得することです。これは、データが古いフレームであることを意味しますが、それに気付くのに十分な速さの反応を人間が持っていないことを意味します。
コメントに対する補足です。
各オブジェクトに一意の色を割り当てるには、オブジェクトごとに 1 バイトをインクリメントします。そのバイトがオーバーフローすると、別のバイトがインクリメントされ、オーバーフローすると別のバイトがインクリメントされます。次に、これらの 3 バイトを赤、緑、青として使用できます。アルファを最大値に保つことを忘れないでください。オブジェクトが透けて見えるのは望ましくありません。
バックバッファを解決するには、XNA4 でわずかに変更します。ここで、rendertarget にレンダリングして解決する必要があります。これを行うのは非常に簡単で、Shawn Hargreaves によって概説されています。