web-dev-qa-db-fra.com

Détection de collision Java entre deux objets Shape?

Je voudrais savoir le meilleur moyen de savoir si un objet Shape croise une autre forme. Actuellement, la détection des collisions dans mon jeu est résolue dans la mesure où il s'agit d'une forme coupant un rectangle ou inversement. Le problème que je rencontre est que la méthode intersects () de la classe Shape peut uniquement prendre un rectangle ou un point en tant que paramètre, pas une autre forme. Existe-t-il un moyen efficace de vérifier si deux objets Shape se chevauchent? Une des méthodes que j’ai essayée consistait à utiliser une boucle for pour générer une zone de points afin de vérifier si elles étaient dans la forme, puis à créer un tableau d’objets Point à envoyer à l’autre forme à tester. des comparaisons inutiles.

J'ai cherché et cherché quelque chose de similaire ici, mais je n'ai rien trouvé vraiment. Désolé d'avance s'il s'agit d'une répétition.

12
Monkeybro10

Non testé, mais pourquoi pas:

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 implémente Shape, mais ajoute des méthodes potentiellement utiles

16
user2221343

Vous pouvez également utiliser les limites de la forme elle-même, puis comparer les limites:

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

C'est un peu plus agréable pour les yeux.

5
TastyLemons

Même si user2221343 a déjà répondu à la question de Monkeybro10, j'ai pensé qu'il pourrait être utile de savoir que le contour d'une forme peut jouer un rôle si vous utilisez sa technique décrite:

Par exemple, si vous tracez deux polygones, leur collision ne sera pas détectée si elle se produit uniquement sur le contour exact des polygones. Seulement, si les zones incluses dans les contours des polygones se chevauchent, la collision est détectée. Si vous remplissez deux polygones, mais ne les tracez pas, la collision sera détectée même sur le contour de la zone visible.

J'ai écrit un petit exemple pour montrer ce que je veux dire. Supprimez la mise en commentaire de la commande draw ou fill et augmentez le second polygone verticalement d’un pixel en supprimant la mise en commentaire de la ligne donnée. Exécutez le code et regardez le résultat dans le cadre JFrame. Si le deuxième polygone est élevé et que les deux polygones ne sont visibles que par la commande "Remplir", ils se coupent avec leurs contours et une collision est détectée. Si le deuxième polygone n'est pas élevé et que les deux polygones sont visibles à l'aide de la commande "dessiner", ils se croisent avec leurs contours mais la collision n'est pas détectée:

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

Si vous pensez que l'intersection de la zone est trop coûteuse, vous pouvez d'abord effectuer une vérification des limites: ShapeA.getBounds (). Intersects (shapeB.getBounds ())

Si cela réussit, alors faites la vérification d'intersection de secteur.

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