web-dev-qa-db-ja.com

Java 2つのShapeオブジェクト間の衝突検出?

Shapeオブジェクトが別の図形と交差するかどうかを確認する最良の方法を知りたいのですが。現在、四角形と交差する形状またはその逆を含む限り、私のゲームで衝突検出が分類されています。私が抱えている問題は、Shapeクラスのintersects()メソッドがパラメーターとして受け取ることができるのは、RectangleまたはPointのみであり、別のShapeではないことです。 2つのShapeオブジェクトが何らかの方法でオーバーラップしているかどうかをテストする効率的な方法はありますか?私が試した方法の1つは、forループを使用してポイントの領域を生成し、それらが形状にあるかどうかをテストしてから、Pointオブジェクトの配列を作成して他の形状に送信してテストしましたが、これにより、フレームレートが大幅に低下しました。不要な比較の。

ここで似たようなものを探して探しましたが、実際には何も見つかりませんでした。これが繰り返しの場合、事前に申し訳ありません。

14
Monkeybro10

テストされていませんが、なぜそうではないのですか?

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はShapeを実装しますが、潜在的に役立ついくつかのメソッドを追加します

18
user2221343

シェイプ自体の境界を使用して、境界を比較することもできます。

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

これは少し目に優しいです。

5
TastyLemons

User2221343はすでにMonkeybro10の質問に回答しましたが、彼の説明した手法を使用する場合、形状の輪郭が役割を果たす可能性があることを知っておくと役立つ場合があると思いました。

たとえば、2つのポリゴンを描画する場合、ポリゴンの正確なアウトライン上でのみ発生すると、それらの衝突は検出されません。ポリゴンのアウトラインの内側に含まれる領域が重なる場合のみ、衝突が検出されます。 2つのポリゴンを塗りつぶし、それらを描画しない場合、可視領域の輪郭上でも衝突が検出されます。

私が意味することを示すために、小さな例を書きました。描画または塗りつぶしコマンドのコメントを外し、指定されたラインのコメントを外して、2番目のポリゴンを垂直方向に1ピクセル上げます。コードを実行し、JFrameで結果を確認します。 2番目のポリゴンが立ち上がっており、両方のポリゴンが「塗りつぶし」コマンドによってのみ表示される場合、それらは輪郭と交差し、衝突が検出されます。 2番目のポリゴンが隆起しておらず、両方のポリゴンが「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");
        }
    }

}
1
Done123

領域の交差が高すぎると思われる場合は、最初に境界チェックを行うことができます:shapeA.getBounds()。intersects(shapeB.getBounds())

これに合格した場合は、エリアの交差チェックを実行します。

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