2011-02-09 11 views
5

私はこのPanelクラスを持っています。これは、あなたがサイズ変更、閉じる、ボタン、スライダなどを加えることができるウィンドウのようなものです.Morrowindのステータス画面のようなものがあります。私が望む振る舞いは、スプライトがパネルの境界線の外にあるときは描画されず、部分的にしか外側にない場合は内側の部分だけが描画されるということです。 これは今、パネルの境界を表す矩形とスプライトの矩形を取得し、その間の交差の矩形を見つけて、その交差をスプライト矩形のローカル座標に変換して使用しますソース矩形の場合はです。それは機能し、私がコードを感じるほど巧妙であるので、これを行う良い方法があるという感覚を揺さぶることはできません。また、この設定では、2Dカメラにグローバル変換マトリックスを使用することはできません。描画するには、「ワールド」のすべてにカメラ引数を渡す必要があります。とにかく、ここで私が持っているコードです:交差点のため
回転した四角形でクリッピングを実行するにはどうすればよいですか?

 public static Rectangle? Intersection(Rectangle rectangle1, Rectangle rectangle2) 
    { 
     if (rectangle1.Intersects(rectangle2)) 
     { 
      if (rectangle1.Contains(rectangle2)) 
      { 
       return rectangle2; 
      } 
      else if (rectangle2.Contains(rectangle1)) 
      { 
       return rectangle1; 
      } 
      else 
      { 
       int x = Math.Max(rectangle1.Left, rectangle2.Left); 
       int y = Math.Max(rectangle1.Top, rectangle2.Top); 
       int height = Math.Min(rectangle1.Bottom, rectangle2.Bottom) - Math.Max(rectangle1.Top, rectangle2.Top); 
       int width = Math.Min(rectangle1.Right, rectangle2.Right) - Math.Max(rectangle1.Left, rectangle2.Left); 
       return new Rectangle(x, y, width, height); 
      } 
     } 
     else 
     { 
      return null; 
     } 
    } 

と、実際にパネルに描画する:

public void DrawOnPanel(IDraw sprite, SpriteBatch spriteBatch) 
    { 
     Rectangle panelRectangle = new Rectangle(
      (int)_position.X, 
      (int)_position.Y, 
      _width, 
      _height); 
     Rectangle drawRectangle = new Rectangle(); 

     drawRectangle.X = (int)sprite.Position.X; 
     drawRectangle.Y = (int)sprite.Position.Y; 
     drawRectangle.Width = sprite.Width; 
     drawRectangle.Height = sprite.Height; 

     if (panelRectangle.Contains(drawRectangle)) 
     { 
      sprite.Draw(
       spriteBatch, 
       drawRectangle, 
       null); 
     } 
     else if (Intersection(panelRectangle, drawRectangle) == null) 
     { 
      return; 
     } 
     else if (Intersection(panelRectangle, drawRectangle).HasValue) 
     { 
      Rectangle intersection = Intersection(panelRectangle, drawRectangle).Value; 

      if (Intersection(panelRectangle, drawRectangle) == drawRectangle) 
      { 
       sprite.Draw(spriteBatch, intersection, intersection); 
      } 
      else 
      { 
       sprite.Draw(
        spriteBatch, 
        intersection, 
        new Rectangle(
         intersection.X - drawRectangle.X, 
         intersection.Y - drawRectangle.Y, 
         intersection.Width, 
         intersection.Height)); 
      } 
     } 
    } 

だから私は私の質問があると思い、行うには良い方法がありますこの?

更新:ちょうどScissorRectangleプロパティについて知りました。これはこれを行うためのまともな方法のようです。 RasterizerStateオブジェクトを作成し、それを受け入れるスプライトバッチに渡す必要があります。しかし、これは最善の策かもしれないようです。私が明らかに変えることができるビューポートもあります。思考? :)

+0

私はあなたの質問に、より明確な定式化を使用することをお勧めします。「回転した長方形でクリッピングを実行する方法」の行に沿ったものです。 – Joh

+0

ああ、うわー、私は回転について考えることさえしなかった。ありがとう –

答えて

1

画面の一部に描画を制限する方法はいくつかあります。領域が長方形の場合(ここではそうです)、ビューポート(GraphicsDeviceを参照)をパネルのサーフェスに設定できます。

矩形以外の領域の場合は、ステンシルバッファを使用するか、深度バッファでいくつかのトリックを使用できます。ステンシルバッファまたはデプスバッファにサーフェスのシェイプを描画し、レンダリングステートを設定して、ステンシル/デプスバッファにレンダリングしたシェイプにあるピクセルのみを描画し、スプライトをレンダリングします。

1

これを行う1つの方法は、単純なピクセル単位の衝突です。スプライトが大きいか多数の場合、これは悪い考えですが、これは小さなスプライトを使って作業を行うための非常に簡単で迅速な方法です。まず、バウンディングサークルまたは四角い衝突チェックをパネルに対して行い、ピクセルごとの検出を行う必要があるかどうかを確認します。

次に、スプ​​ライトの位置、大きさ、回転がパネル内にあるかどうかを確認するcontainsメソッドを作成して、パネルによって完全に囲まなければならないので、ピクセルごとの衝突は必要ありませんその場合は。これは、スプライトの対角線の長さの幅と高さを持つ境界の四角形を作成し、スプライトの対角線の衝突をチェックするだけで簡単に行うことができます。

最後に、これらの両方が失敗した場合、ピクセル単位の衝突を実行する必要があります。スプライト内のすべてのピクセルを調べて、それがパネルの範囲内にあるかどうかを確認します。設定されていない場合、ピクセルのアルファ値は0に設定されます。

です。

関連する問題