2012-09-06 9 views
6

Sto cercando di impostare alcune semplici forme 2D che possono essere trascinate sulla finestra usando il mouse. Voglio che le forme registrino una collisione quando ne trascino una nell'altra. Ho un'interfacciaUso del polimorfismo per il rilevamento delle collisioni in modo elegante

interface ICollidable 
{ 
    bool CollidedWith(Shape other); 
} 

Ho quindi una classe astratta Shape che implementa l'interfaccia di cui sopra.

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); 
} 

Ho quindi dieci classi concrete Circle, Square, Rectangle ecc che estendono la classe Shape e implementano i metodi astratti. Quello che vorrei fare è trovare un qualche oop modo pulito ed elegante per fare il rilevamento collosion invece avere un grande blocco di istruzioni if ​​nel metodo CollidedWith tale è

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 
} 

Qualcuno ha tutte le idee. È un problema a cui ho pensato prima, ma sto solo mettendo in pratica adesso.

+0

Sarebbe utile se si potesse spiegare come si sta definendo una collisione e come potrebbe variare tra le sottoclassi. 'Shape' conterrà anche qualsiasi informazione sulle coordinate delle istanze? – mclark1129

+0

@Mick C. Ho modificato il codice inserendo l'intero codice per la classe Shape –

risposta

1

Invece di forme specifiche, tutti sono TUTTI sono Paths o Regions.

Un quadrato è solo un poli con 4 punti, che si trovano ad angolo retto. Quindi scrivi solo un metodo Path.CollidesWith(Path) e procedi.

Verificare alcuni relatedquestions.

4

è il rilevamento di collisione in modo "forma specifica" che c'è un'implementazione diversa per ogni permutazione di

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

Suona come si sta cercando di creare una matrice di tutte le possibilità, ma se si arriva con 10 nuove forme, 20 in totale, hai 400 possibilità.

Invece, proverei a trovare un metodo generico Shape.Overlaps(Shape other) nella classe astratta che soddisfi tutti loro.

Se questa è solo geometria 2D, se dovrebbe essere banale per capire se i percorsi del bordo di qualsiasi forma si intersecano.

1

Double dispatch è comunemente utilizzato in questa situazione.

+1

Se ci pensate, questo non è poi così diverso dal metodo 'CollideWith' dell'OP con l'istruzione if grande. L'unica differenza è che il framework gestirà la logica di commutazione per te. L'altro problema è che questo approccio richiede ancora di modificare ogni sottoclasse e fornire una nuova implementazione per ogni nuovo tipo che viene creato, il che comporterebbe un onere di manutenzione in crescita esponenziale. – mclark1129