2013-03-28 17 views
10

Vorrei sapere il modo migliore per sapere se un oggetto Forma interseca un'altra forma. Attualmente ho il rilevamento delle collisioni nel mio gioco risolto a patto che coinvolga una forma che interseca un rettangolo o viceversa. Il problema che sto avendo è che il metodo intersects() nella classe Shape può solo prendere un Rectangle o un Point come parametro, non un altro Shape. Esiste un modo efficace per verificare se due oggetti Shape si sovrappongono in qualche modo? Un modo in cui ho provato è stato utilizzare un ciclo for per generare un'area di punti per verificare se erano nella forma e quindi creare una serie di oggetti Point da inviare all'altra forma da testare, ma questo ha significativamente ridotto il framerate a causa di tutti i confronti non necessari.Rilevamento della collisione Java tra due oggetti Shape?

Ho cercato e cercato qualcosa di simile qui ma non ho trovato nulla di veramente. Scusa in anticipo se questa è una ripetizione.

+1

Sta considerando solo il riquadro di delimitazione della forma sufficiente per forme complesse? Se è così, allora è semplice. In caso contrario, penso che diventi un po 'complicato ... – souldzin

+0

No, il riquadro di selezione non funzionerà. Deve essere il perimetro effettivo della forma. Ho provato a usare il metodo getBounds(), ma se provi a spostare il tuo personaggio in diagonale oltre un muro, rimangono bloccati anche se lo sprite non lo sta colpendo. – Monkeybro10

risposta

15

non testato, ma perché non:

import java.awt.geom.Area; 

... 

public static boolean testIntersection(Shape shapeA, Shape shapeB) { 
    Area areaA = new Area(shapeA); 
    areaA.intersect(new Area(shapeB)); 
    return !areaA.isEmpty(); 
} 

Area implementa Forma, ma aggiunge alcuni metodi potenzialmente utili

+4

Funziona esattamente come volevo! Grazie mille. – Monkeybro10

+0

Felice di aiutare :) – user2221343

+1

Questo non crea un sacco di spazzatura? – TastyLemons

1

Anche se user2221343 già risposto alla domanda di Monkeybro10, ho pensato che potrebbe essere utile in alcuni casi sapere che il contorno di una forma potrebbe avere un ruolo se si utilizza la sua tecnica descritta:

Ad esempio, se si disegna due poligoni, la collisione di essi non verrà rilevata se si verifica solo sulla sagoma esatta di i poligoni. Solo se le aree incluse all'interno dei contorni dei poligoni si sovrappongono, viene rilevata la collisione. Se si riempiono due poligoni, ma non li si disegna, la collisione verrà rilevata anche sul contorno dell'area visibile.

Ho scritto un piccolo esempio per mostrare cosa intendo. Annullare il comando di estrazione o di riempimento e sollevare il secondo poligono verticalmente di un pixel rimuovendo il commento dalla linea indicata. Esegui il codice e guarda il risultato in JFrame. Se il secondo poligono è aumentato e entrambi i poligoni sono visibili solo dal comando "riempimento", si intersecano con i loro contorni e viene rilevata la collisione. Se il secondo poligono non è risorto, ed entrambi i poligoni sono visibili dal comando "tracciare", si intersecano con i loro contorni ma collisione non viene rilevato:

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Polygon; 
import java.awt.geom.Area; 

import javax.swing.JFrame; 

public class Test { 

    private JFrame frame; 
    private Polygon polygon1; 
    private Polygon polygon2; 

    /** 
    * Launch the application. 
    */ 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        Test window = new Test(); 
        window.frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    /** 
    * Create the application. 
    */ 
    public Test() { 
     initialize(); 
    } 

    /** 
    * Initialize the contents of the frame. 
    */ 
    private void initialize() { 
     frame = new JFrame(){ 
      private static final long serialVersionUID = 1L; 

      @Override 
      public void paint(Graphics g){ 

       super.paint(g); 

       doDrawing(g); 

      } 
     }; 
     frame.setBounds(100, 100, 450, 300); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     int nShape1 = 4; 
     int xPoly1[] = {30,50,50,30}; 
     int yPoly1[] = {30,30,50,50}; 
     polygon1 = new Polygon(xPoly1,yPoly1,nShape1); 

     int nShape2 = 4; 
     int xPoly2[] = {35,55,55,35}; 
     int yPoly2[] = {50,50,70,70}; 

     // uncomment next line to rise second polygon vertically by one pixel 
     //yPoly2[] = {49,49,69,69}; 

     polygon2 = new Polygon(xPoly2,yPoly2,nShape2); 
    } 
    public synchronized void doDrawing(Graphics g){ 
     g.setColor(new Color(255,0,0)); 

     // if you draw the polygon, collision on the exact outline won't be detected. 
     // uncomment draw or fill command to see what I mean. 
     g.drawPolygon(polygon1); 
     g.fillPolygon(polygon1); 

     g.setColor(new Color(0,0,255)); 

     // if you draw the polygon, collision on the exact outline won't be detected. 
     // uncomment draw or fill command to see what I mean. 
     g.drawPolygon(polygon2); 
     g.fillPolygon(polygon2); 

     Area area = new Area(polygon1); 
     area.intersect(new Area(polygon2)); 
     if(!area.isEmpty()){ 
      System.out.println("intersects: yes"); 
     } 
     else{ 
      System.out.println("intersects: no"); 
     } 
    } 

} 
5

È anche possibile utilizzare i limiti della forma stessa e poi confronta i limiti:

public boolean collidesWith(Shape other) { 
    return shape.getBounds2D().intersects(other.getBounds2D()); 
} 

Questo è un po 'più bello per gli occhi.

+1

Questo darà una collisione in bounding box piuttosto che l'intersezione della forma che il richiedente vuole. Tuttavia, non vale nulla che sia molto probabilmente molto più performante della mia risposta. Per uno, non c'è bisogno di fare copie difensive, dal momento che questo metodo "interseca" non modifica la forma. Inoltre, il contratto per questo "intersezione" specifica che l'accuratezza può essere ridotta a favore delle prestazioni: http://docs.oracle.com/javase/7/docs/api/java/awt/geom/RectangularShape.html#intersects (java.awt.geom.Rectangle2D) – user2221343

Problemi correlati