2012-09-06 8 views
6

マウスを使用してウィンドウについてドラッグできる単純な2Dシェイプを設定しようとしています。私は形を別のものにドラッグすると、衝突を登録するようにしたい。私はインターフェイスを持っています。多面体を使用したエレガントな衝突検出

interface ICollidable 
{ 
    bool CollidedWith(Shape other); 
} 

私は上記のインターフェイスを実装する抽象クラスShapeを持っています。

abstract class Shape : ICollidable 
{ 
    protected bool IsPicked { private set; get; } 
    protected Form1 Form { private set; get; } 

    protected int X { set; get; } // Usually top left X, Y corner point 
    protected int Y { set; get; } // Used for drawing using the Graphics object 

    protected int CenterX { set; get; } // The center X point of the shape 
    protected int CenterY { set; get; } // The center X point of the shape 

    public Shape(Form1 f, int x, int y) 
    { 
     Form = f; 
     X = x; Y = y; 
     Form.MouseDown += new MouseEventHandler(form_MouseDown); 
     Form.MouseMove += new MouseEventHandler(Form_MouseMove); 
     Form.MouseUp += new MouseEventHandler(Form_MouseUp); 
    } 

    void Form_MouseMove(object sender, MouseEventArgs e) 
    { 
     if(IsPicked) 
      Update(e.Location); 
    } 

    void Form_MouseUp(object sender, MouseEventArgs e) 
    { 
     IsPicked = false; 
    } 

    void form_MouseDown(object sender, MouseEventArgs e) 
    { 
     if (MouseInside(e.Location)) 
      IsPicked = true; 
    } 

    protected abstract bool MouseInside(Point point); 
    protected abstract void Update(Point point); 
    public abstract void Draw(Graphics g); 
    public abstract bool CollidedWith(Shape other); 
} 

次に、Shapeクラスを拡張して抽象メソッドを実装する10個の具象クラスCircle、Square、Rectangleなどがあります。私がやりたい何 ではなく、そのようなCollidedWith方法で文が

public bool CollidedWith(Shape other) 
{ 
    if(other is Square) 
    { 
     // Code to detect shape against a square 
    } 
    else if(other is Triangle) 
    { 
     // Code to detect shape against a triangle 
    } 
    else if(other is Circle) 
    { 
     // Code to detect shape against a circle 
    } 
    ... // Lots more if statements 
} 

が任意のアイデア誰を持っている場合の大きなブロックを持つcollosion検出を行うには、いくつかのOOPクリーンかつエレガントな方法を考え出すされています。これは私が以前考えていた問題ですが、今は実践しています。

+0

どのようにして衝突を定義するのか、そしてサブクラス間でどのように変化するのか説明できると便利です。 'Shape'にはインスタンス座標に関する情報も含まれていますか? – mclark1129

+0

@Mick C.シェイプクラスのコード全体を挿入するコードを変更しました –

答えて

1

特定の形状の代わりに、ALLはすべてPathsまたはRegionsです。

正方形はちょうど4ポイントのポリですが、それは直角であることがあります。次に、Path.CollidesWith(Path)メソッドを1つ書き込んでください。

relatedquestionsをチェックしてください。

4

はあなたが10を思い付く場合

Circle vs. Other Circle 
Circle vs. Other Square 
Circle vs. Other Triangle 
Square vs. Other Circle 
... 

のすべての順列に異なる実装があることそれはあなたがすべての可能性のマトリックスを作成しようとしているように聞こえるが、そう、「具体的な形状」の衝突検出であります新しい形、合計で20、あなたは400の可能性があります。

代わりに、抽象クラスで、すべてを満たすような汎用のShape.Overlaps(Shape other)メソッドを試してみます。

これはちょうど2Dジオメトリであれば、任意の図形のエッジパスが交差するかどうか把握するのは簡単です。

1

Double dispatchがこの状況で一般的に使用されます。

+1

これについて考えると、大規模なif文を使用したOPの 'CollideWith'メソッドとはまったく異なるわけではありません。唯一の違いは、フレームワークがスイッチングロジックを処理することです。もう1つの問題は、このアプローチでは、すべてのサブクラスを変更し、作成されるすべての新しいタイプに対して新しい実装を提供する必要があり、指数関数的にメンテナンスの負担が増大することです。 – mclark1129