旋转矩形的碰撞检测 [英] Collision Detection with Rotated Rectangles

查看:345
本文介绍了旋转矩形的碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个乒乓球游戏。但是,在我的游戏中,桨板可以绕其中心旋转。

I am creating a pong game. However, in my game, the paddles have the ability to rotate about their center.

这些桨板由矩形2D对象表示。现在,这些矩形应该会碰到它们。球由一个circle2D对象表示,当球击中球拍时(这是通过使用矩形的相交方法完成的),球将反转方向。当不旋转拨片时,这种方法效果很好,但是当它们旋转时,相交方法不起作用。当我使用以下语句时:

These paddles are represented by rectangle2D objects. Now, these rectangles are supposed to hit the ball as it comes to them. The ball is represented by a circle2D object, and when the ball hits the paddle (this is done by using the intersects method of the rectangles), the ball reverses direction. This works fine when the paddles are not rotated, but when they are rotated, the intersects method doesn't work. When I use this statement:

paddle2.intersects(xLocation, yLocation, diameter, diameter)

(其中paddle2是其中一个矩形的名称,传递给它的参数表示x坐标,y坐标和半径圆)

(Where paddle2 is the name of one of the rectangles, and the parameters passed to it represent the x coordinate, y coordinate, and radius of the circle)

圆的作用就像矩形没有旋转一样。也就是说,它将从矩形的原始位置反弹。

The circle acts as if the rectangle isn't rotated. That is, it will bounce off the rectangles original position.

我可能应该提到我使用仿射变换来旋转矩形。这是我用来使矩形显示为旋转的命令:

I should probably mention that I am rotating the rectangles using affine transforms. This is the command I use to make the rectangle appear rotated:

g2.rotate(Math.toRadians(angle), xLocation+(width/2), yLocation+(height/2)); 

(其中参数是矩形的旋转角度以及中心的x和y坐标)。

(where the parameters are the rotation angle of the rectangle, and the x and y coordinates of the center).

然后,我将我的g2对象的仿射变换重置为常规仿射变换。

Then, I reset the affine transform of my g2 object back to a regular affine transform.

我研究这个问题已有一段时间了,并且找到了关于这个问题的一些讨论。但是,它们似乎在我头上,并且似乎在处理矩阵数学(作为一个从未学习过必要数学的人,我很迷茫)。因此,我希望有人能够提供一个简单的解决方案,或者引导我完成所需的数学运算。

I have been researching this problem for awhile now, and I have found a couple discussions on the problem. However, they seem to be over my head, and they seem to deal with matrix mathematics (and as someone who has never learned the necessary math, I get quite lost). So, I was hoping that someone could provide a simple solution, or walk me through the required math.

谢谢!

推荐答案

也许这是一个古老的问题,但是我认为对于其他将要阅读此帖子的人都有解决方案:

Maybe this is an old question, but I think to have the solution for anyone else that will read this post:

/** Rectangle To Point. */
boolean testRectangleToPoint(double rectWidth, double rectHeight, double rectRotation, double rectCenterX, double rectCenterY, double pointX, double pointY) {
    if(rectRotation == 0)   // Higher Efficiency for Rectangles with 0 rotation.
        return Math.abs(rectCenterX-pointX) < rectWidth/2 && Math.abs(rectCenterY-pointY) < rectHeight/2;

    double tx = Math.cos(rectRotation)*pointX - Math.sin(rectRotation)*pointY;
    double ty = Math.cos(rectRotation)*pointY + Math.sin(rectRotation)*pointX;

    double cx = Math.cos(rectRotation)*rectCenterX - Math.sin(rectRotation)*rectCenterY;
    double cy = Math.cos(rectRotation)*rectCenterY + Math.sin(rectRotation)*rectCenterX;

    return Math.abs(cx-tx) < rectWidth/2 && Math.abs(cy-ty) < rectHeight/2;
}

/** Circle To Segment. */
boolean testCircleToSegment(double circleCenterX, double circleCenterY, double circleRadius, double lineAX, double lineAY, double lineBX, double lineBY) {
    double lineSize = Math.sqrt(Math.pow(lineAX-lineBX, 2) + Math.pow(lineAY-lineBY, 2));
    double distance;

    if (lineSize == 0) {
        distance = Math.sqrt(Math.pow(circleCenterX-lineAX, 2) + Math.pow(circleCenterY-lineAY, 2));
        return distance < circleRadius;
    }

    double u = ((circleCenterX - lineAX) * (lineBX - lineAX) + (circleCenterY - lineAY) * (lineBY - lineAY)) / (lineSize * lineSize);

    if (u < 0) {
        distance = Math.sqrt(Math.pow(circleCenterX-lineAX, 2) + Math.pow(circleCenterY-lineAY, 2));
    } else if (u > 1) {
        distance = Math.sqrt(Math.pow(circleCenterX-lineBX, 2) + Math.pow(circleCenterY-lineBY, 2));
    } else {
        double ix = lineAX + u * (lineBX - lineAX);
        double iy = lineAY + u * (lineBY - lineAY);
        distance = Math.sqrt(Math.pow(circleCenterX-ix, 2) + Math.pow(circleCenterY-iy, 2));
    }

    return distance < circleRadius;
}

/** Rectangle To Circle. */
boolean testRectangleToCircle(double rectWidth, double rectHeight, double rectRotation, double rectCenterX, double rectCenterY, double circleCenterX, double circleCenterY, double circleRadius) {
    double tx, ty, cx, cy;

    if(rectRotation == 0) { // Higher Efficiency for Rectangles with 0 rotation.
        tx = circleCenterX;
        ty = circleCenterY;

        cx = rectCenterX;
        cy = rectCenterY;
    } else {
        tx = Math.cos(rectRotation)*circleCenterX - Math.sin(rectRotation)*circleCenterY;
        ty = Math.cos(rectRotation)*circleCenterY + Math.sin(rectRotation)*circleCenterX;

        cx = Math.cos(rectRotation)*rectCenterX - Math.sin(rectRotation)*rectCenterY;
        cy = Math.cos(rectRotation)*rectCenterY + Math.sin(rectRotation)*rectCenterX;
    }

    return testRectangleToPoint(rectWidth, rectHeight, rectRotation, rectCenterX, rectCenterY, circleCenterX, circleCenterY) ||
            testCircleToSegment(tx, ty, circleRadius, cx-rectWidth/2, cy+rectHeight/2, cx+rectWidth/2, cy+rectHeight/2) ||
            testCircleToSegment(tx, ty, circleRadius, cx+rectWidth/2, cy+rectHeight/2, cx+rectWidth/2, cy-rectHeight/2) ||
            testCircleToSegment(tx, ty, circleRadius, cx+rectWidth/2, cy-rectHeight/2, cx-rectWidth/2, cy-rectHeight/2) ||
            testCircleToSegment(tx, ty, circleRadius, cx-rectWidth/2, cy-rectHeight/2, cx-rectWidth/2, cy+rectHeight/2);
}

这是测试圆(球)与球之间的碰撞的代码矩形(可以旋转)。

This is the code to test Collisions between a circle (The Ball) and a rectangle (That can rotate).

这篇关于旋转矩形的碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆