0

ラベル、リストボックス、テキストボックス、パネルなどの単純なウィンドウインターフェイスオブジェクトをC#XNAで再現しようとしています。結果として、すべてのオブジェクトは、オブジェクトを描画して更新する基本的な抽象クラス(XNAInterfaceObject)から派生します。updateメソッドでは、マウスとキーボードを操作してさまざまなイベントを発生させます。問題は、2つのインターフェイスオブジェクトが互いに重なり合っており(たとえば、リストボックス上のポップアップコンテキストメニュー)、両方にnull以外のイベントがある場合です。コードは、最上位のオブジェクトのイベントが必要な場合に、両方のイベントを発生させます。どのオブジェクトが一番上にあるかを確認するにはどうすればよいですか?または、どういうわけか上部のオブジェクトを下部のオブジェクトとオーバーラップさせます。最後にクリックされたオブジェクトの参照を保持するグローバル変数について考えました。他のオブジェクトは、この変数がnullかどうかをチェックして、イベントを続行します。

私の言語は申し訳ありませんが、私は英語を母国語とはしていません。

4

3 に答える 3

1

私はおそらくこの問題を2つの要素に分解するでしょう:

  1. インターフェイスオブジェクトの順序を決定します。
  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;
}

とにかく、それが私の考えです。夜はかなり遅いので、すべてが賢明であり、明白な間違いがないことを願っています。

于 2012-06-20T14:31:36.850 に答える
0

通常、GUIには、何が何の上にあるかを維持する可視性の順序(zオーダー)のリストがあります。この手法(各コンポーネントにazオーダーを割り当てる)を使用すると、クリックされた座標を含む、クリックされたコンポーネントの上部に何かがあるかどうかを確認できます。ある場合は、クリックを処理しないでください(他のコンポーネントは上に、それはそれを処理します); それ以外の場合、このコンポーネントはクリックを処理するための最上位のコンポーネントです

于 2012-06-20T14:01:56.447 に答える
0

簡単な解決策は、ゲームクラスにリストを作成することです。

List<XNAInterfaceObject> controls;

その後、問題のリストの順序を使用できます。リストの最初の要素を、最前面にあるコントロールと考えてください。ゲームのGetControlAt()メソッドでは、コントロールを前から後ろにループできます。

protected override void Update(GameTime gameTime)
{
    ...

    MouseState ms = Mouse.GetState();
    if (ms.LeftButton == ButtonState.Pressed)
    {
        XNAInterfaceObject control = GetControlAt(ms.X, ms.Y);
        if (control != null)
            control.MouseClickMethod(ms);
    }

    ...
}

private XNAInterfaceObject GetControlAt(int x, int y)
{
    for (int i = 0; i < controls.Count; i++)
    {
        if (controls[i].Rectangle.Contains(x, y)
        {
            return controls[i];
        }
    }
    return null;
}

これは、XNAInterfaceObjectにRectangleプロパティとMouseClickMethod()が必要であることを意味します。コントロールを描画するときは、リストを逆方向にループする必要があることに注意してください。

于 2012-06-20T15:57:38.443 に答える