Обнаружение столкновения Java между двумя объектами формы?

Я хотел бы знать, как лучше всего определить, пересекает ли объект формы другую форму. В настоящее время у меня есть обнаружение столкновений в моей игре, если оно включает фигуру, пересекающую прямоугольник или наоборот. Проблема в том, что метод intersects() в классе Shape может принимать в качестве параметра только прямоугольник или точку, а не другую фигуру. Есть ли эффективный способ проверить, перекрываются ли два объекта формы каким-либо образом? Один способ я пробовал с помощью цикла for с создайте область точек, чтобы проверить, были ли они в форме, а затем создайте массив точечных объектов для отправки в другую форму для тестирования, но это значительно снизило мою частоту кадров из-за всех ненужных сравнений.

Я искал и искал что-то подобное здесь, но ничего не нашел. Заранее извините, если это повторится.

4 ответов


Не проверял, но почему бы и нет:

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

область реализует форму, но добавляет некоторые потенциально полезные методы


вы также можете использовать границы самой формы, а затем сравнить границы:

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

Это немного приятнее на глаз.


хотя user2221343 уже ответил на вопрос Monkeybro10, я подумал, что в некоторых случаях может быть полезно знать, что контур фигуры может сыграть определенную роль, если вы используете его описанную технику:

например, если вы рисуете два полигона, столкновение их не будет обнаружено, если оно происходит только на точном контуре полигонов. Только если области, включенные в контуры полигонов, будут перекрываться, столкновение будет обнаружено. Если заполнить два полигона, но не рисуйте их, столкновение будет обнаружено даже на контуре видимой области.

Я написал небольшой пример, чтобы показать, что я имею в виду. Раскомментируйте команду draw или fill и поднимите второй многоугольник вертикально на один пиксель, раскомментировав данную строку. Запустите код и посмотрите результат в JFrame. Если второй многоугольник поднят, и оба многоугольника видны только командой "fill", они пересекаются с их контурами и обнаруживается столкновение. Если второй полигон не поднимается, и оба полигона видны командой "draw", они пересекаются с их контурами, но столкновение не обнаружено:

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

}

Если вы считаете, что пересечение области слишком дорого, вы можете сначала сделать проверку границ: shapeA.getBounds ().пересекается(shapeB.getBounds ())

Если это пройдет, то сделайте проверку пересечения области.

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