私はおそらくこの問題を2つの要素に分解するでしょう:
- インターフェイスオブジェクトの順序を決定します。
- オーバーラップがある場合にのみ、最上位のオブジェクトでイベントをトリガーします。
パート1の対処は簡単です。オブジェクトの深さを指定する「layer」フィールド/プロパティを基本クラスに含めます。ほとんどのゲームノードクラスでは、描画に役立つため、これを含めます。状況が少し複雑になる場合は、インターフェイスの順序付けに別のレイヤリングシステムが必要になる場合があります。このアプローチの欠点は、レイヤが同じであるオーバーラップを取得できることです。
@Attilaが提案しているように、それ以外の場合は、インターフェイス要素のZ順リストを管理できます。この場合、順序付けはインデックスによって管理され、管理は簡単ですが、追加の処理なしにこの情報を描画に使用することはできず、単純な値の比較ほど速くはありません。
財産
public class InterfaceComponent
{
// Class members...
private float layer;
public float Layer { get { return layer; } set { layer = Math.Abs(value); } }
public bool InFrontOf(InterfaceComponent other) { return this.Layer < other.Layer; }
}
Zオーダーリスト
public class InterfaceComponent
{
private static List<InterfaceComponent> zOrder = new List<InterfaceComponent>();
// Class Members....
public InterfaceComponent()
{
// Construct class...
zOrder.Add(this);
}
private void SetZOrder(int order)
{
if (order < 0 || order >= zOrder.Count)
return;
zOrder.Remove(this);
zOrder.Insert(order, this);
// There are more efficient ways, but you get the idea.
}
public void SendBack() { SetZOrder(zOrder.indexOf(this) + 1); }
public void SendToFront() { SetZOrder(0); }
// etc...
}
パート2パート2
にアプローチする方法は複数あります。最も明白なのは、交差点とレイヤープロパティのすべてのインターフェイスコンポーネントに対してチェックを実行することです。Z順リストの場合は、交差点のリストの上位にあるすべてのコンポーネント(私の例では0に近づいています)を実行します。
画面を使用してリストを小さくしたとしても、これはかなり高価になる可能性があります。代わりに、発生したイベントのリストを管理し、入力を処理した後にそれらを処理できます。例えば...
public static class InterfaceEvents
{
public static List<EventData> List = new List<EventData>();
public static void Resolve()
{
while (List.Count > 0)
{
for (int i = List.Count - 1; i > 0; i--)
{
if (List[i].EventType == List[0].EventType && List[i].Sender.Intersects(List[0].Sender))
{
if (List[i].Sender.Layer < List[0].Layer) // However you choose to manage it.
{
List[0] = List[i];
List.RemoveAt(i);
}
else
List.RemoveAt(i);
}
}
// Toggle event from List[0]
List.RemoveAt(0);
}
}
}
public struct EventData
{
public InterfaceComponent Sender;
public int EventType;
}
とにかく、それが私の考えです。夜はかなり遅いので、すべてが賢明であり、明白な間違いがないことを願っています。