it-swarm.com.de

Java-Kollisionserkennung zwischen zwei Shape-Objekten?

Ich würde gerne wissen, wie ich am besten feststellen kann, ob ein Shape-Objekt eine andere Shape schneidet. Derzeit wird die Kollisionserkennung in meinem Spiel so lange sortiert, wie es sich um eine Form handelt, die ein Rechteck schneidet, oder umgekehrt. Das Problem, das ich habe, ist, dass die intersects () -Methode in der Shape-Klasse nur ein Rechteck oder einen Punkt als Parameter annehmen kann, keine andere Shape. Gibt es eine effiziente Möglichkeit zu testen, ob sich zwei Shape-Objekte in irgendeiner Weise überlappen? Zum einen habe ich versucht, mit einer for-Schleife einen Bereich von Punkten zu generieren, um zu testen, ob sie die Form haben, und dann ein Array von Point-Objekten zu erstellen, um sie an die andere Form zu senden, um sie zu testen der unnötigen Vergleiche.

Ich habe hier nach etwas Ähnlichem gesucht, aber nicht wirklich etwas gefunden. Entschuldigung im Voraus, wenn dies eine Wiederholung ist.

12
Monkeybro10

Nicht getestet, aber warum nicht:

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 implementiert Shape, fügt jedoch einige potenziell nützliche Methoden hinzu

16
user2221343

Sie können auch die Grenzen der Form selbst verwenden und dann die Grenzen vergleichen:

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

Das ist ein bisschen schöner für die Augen.

5
TastyLemons

Obwohl user2221343 die Frage von Monkeybro10 bereits beantwortet hat, dachte ich, dass es in einigen Fällen hilfreich sein könnte, zu wissen, dass die Kontur einer Form eine Rolle spielen könnte, wenn Sie die beschriebene Technik verwenden:

Wenn Sie beispielsweise zwei Polygone zeichnen, wird deren Kollision nicht erkannt, wenn sie nur auf der exakten Kontur der Polygone auftritt. Nur wenn sich die Bereiche, die in den Umrissen der Polygone enthalten sind, überlappen, wird die Kollision erkannt. Wenn Sie zwei Polygone füllen, aber nicht zeichnen, wird die Kollision sogar auf der Umrisslinie des Polygons erkannt sichtbarer Bereich.

Ich habe ein kleines Beispiel geschrieben, um zu zeigen, was ich meine. Entkommentieren Sie entweder den Befehl draw oder fill und erhöhen Sie das zweite Polygon vertikal um ein Pixel, indem Sie die angegebene Linie auskommentieren. Führen Sie den Code aus und beobachten Sie das Ergebnis im JFrame. Wenn das zweite Polygon angehoben ist und beide Polygone nur durch den Befehl "fill" sichtbar sind, überschneiden sie sich mit ihren Umrissen und die Kollision wird erkannt. Wenn das zweite Polygon nicht angehoben ist und beide Polygone durch den Befehl "draw" sichtbar sind, schneiden sie sich mit ihren Umrissen, es wird jedoch keine Kollision erkannt:

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

}
1
Done123

Wenn Sie denken, dass der Flächenschnitt zu teuer ist, könnten Sie zunächst eine Begrenzungsprüfung durchführen: ShapeA.getBounds (). Schneidet (shapeB.getBounds ())

Wenn dies erfolgreich ist, prüfen Sie die Schnittmenge.

if( myShape.getBounds().intersects(otherShape.getBounds()) ){
    Area a = new Area(myShape);
    a.intersect(new Area(otherShape));
    if(!a.isEmpty()){
        // do something
    }
}
0
Lance Wentz