圆形的碰撞检测

4

我有一个简单的Java小程序,使用java.awt绘制了两个用户可控的球。我需要一种检测它们之间碰撞的方法。我已经有一种检测与墙壁碰撞的算法:

if (xPosition > (300 - radius)){
   xSpeed = -xSpeed; 
}
else if (xPosition < radius){
   xSpeed = -xSpeed; 
}
else if (yPosition > (300 - radius)) {
   ySpeed = -ySpeed;
}
else if (yPosition < radius){
   ySpeed = -ySpeed;
}
xPosition += xSpeed;
yPosition += ySpeed;

对于第二个球:

if (xPosition2 > (300 - radius)){
   xSpeed2 = -xSpeed2; 
}
else if (xPosition2 < radius){
   xSpeed2 = -xSpeed2; 
}
else if (yPosition2 > (300 - radius)) {
   ySpeed2 = -ySpeed2;
}
else if (yPosition2 < radius){
   ySpeed2 = -ySpeed2;
}
xPosition2 += xSpeed2;
yPosition2 += ySpeed2;
  • 应用程序是300像素乘以300像素。
  • radius 存储圆的半径。
  • xPositionxPosition2 存储两个球的 x 坐标。
  • yPositionyPosition 存储两个球的 y 坐标。
  • xSpeedxSpeed2 存储两个球的 x 速度。
  • ySpeedySpeed2 存储两个球的 y 速度。

欢迎来到SO,Bob。这实际上更像是一个数学问题而不是一个编程问题,因为Java语言中没有内置的方法可以实现你想要的功能。不过,为了让你有个开始,可以这样考虑:检测碰撞意味着检测球何时会重叠或接触,对吧?而你知道它们的位置和大小... - Pops
是的,但我想不出任何东西。 我尝试通过数学来解决它,结果得到了球互相穿过和大约30行无用代码。 - Bob Twinkles
4个回答

6

太棒了,谢谢!我听说过一个交叉命令...但显然它只适用于矩形。 - Bob Twinkles
纪念Bob Twinkles,我+1。 - Anthony Forloney
我刚刚看了一下,但是你如何将位置传递给该方法? - Bob Twinkles
你需要实例化Point2d。我建议你使用这个类来存储位置。 - Beothorn
声明一个点作为字段,并使用position.getX()和position.getY()。碰撞测试:boolean isColliding = position.distance(anotherBall.getPosition()) < radius + anotherBall.getRadius; int startingXPosition = 0; int startingYPosition = 0; java.awt.Point position = new java.awt.Point(startingXPosition, startingYPosition); - Beothorn

1
Java中有Point2D,或者你可以自己实现。对于圆与圆之间的碰撞或球与球之间的碰撞来说,这是非常容易的。
int distXX = (xPosition1 - xPosition2) * (xPosition1 - xPosition2);
int distYY = (yPosition1 - yPosition2) * (yPosition1 - yPosition2);
if ( radius*radius > distXX * distYY ) {
   ...  // There's a collision
}

1
请注意,典型的游戏开发新手错误是使用“平方根”来计算距离并检查半径,而不是不进行平方根运算并使用半径x半径进行检查。上面的解决方案仅使用离散匹配,实际上是许多游戏中使用的方法(几十年前我就在编写游戏时采用了这种方式)。 - SyntaxT3rr0r
好的,我刚刚编译并运行了代码,球与其他物体发生了碰撞,但没有与另一个球发生碰撞。 - Bob Twinkles

0
 public boolean colliding(Ball anotherBall) {
    double xDelta = (this.x + this.ballSize/2 + this.dx) - (anotherBall.x + anotherBall.ballSize/2 + anotherBall.dx);
    double YDelta = (this.y + this.ballSize/2 + this.dy) - (anotherBall.y + anotherBall.ballSize/2 + anotherBall.dy);
    double distance = Math.sqrt(Math.pow(xDelta, 2) + Math.pow(YDelta, 2));

    return (distance <= this.ballSize/2 + anotherBall.ballSize/2);

}

那很好,但我正在运行整个应用程序的一个类。 - Bob Twinkles

-1

这个链接非常有用!

圆与圆之间的碰撞

它非常详细和易于理解。


在那个页面的底部还有其他链接,指向更详细的内容!


我使用了“圆心距离法” --- 圆形

通过测量每个圆心之间的距离,您可以判断它们是否发生碰撞。这个距离永远不应该超过两个半径之和。

以下是我的做法:

private boolean checkDrawContains(ShapeDrawable newHole) 
{
    long newCenterX = newHole.getBounds().left + (newHole.getBounds().width()/2); //Get the center of my shapes
    long newCenterY = newHole.getBounds().top + (newHole.getBounds().height()/2);

    for(ShapeDrawable hole: mHoles) // I was storing the circles in an ArrayList
    { 
        long centerX = hole.getBounds().left + (hole.getBounds().width()/2); //Get the center of my shapes
        long centerY = hole.getBounds().top + (hole.getBounds().height()/2);
        long x = centerX - newCenterX;
        long y = centerY - newCenterY;
        long aux = (long) ((Math.pow(Math.abs(x),2)) + (Math.pow(Math.abs(y),2))); //Pythagoras the hard way :P
        long distance = (long) Math.sqrt(aux);
        long sRads = (newHole.getBounds().width()/2) + (hole.getBounds().width()/2);

        if(distance <=  sRads ) {
            return true;  //Is Colliding!
        }
    }
    return false; // Is not Colliding!
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接