球有时弹有时不弹

Ball sometimes bounces sometimes doesn't

此代码使球在 canvas 周围反弹:

//advance the ball
ball.advance();
//check if ball should bounce off canvas sides
if (ball.getCenterX() + ball.getRadius() > canvas.getWidth())
    ball.setDirectionX(LEFT);
if (ball.getCenterX() - ball.getRadius() < 0)
    ball.setDirectionX(RIGHT);

if (ball.getCenterY() + ball.getRadius() > canvas.getHeight())
    ball.setDirectionY(UPWARDS);
if (ball.getCenterY() - ball.getRadius() < 0)
    ball.setDirectionY(DOWNWARDS);

看起来像这样:https://gyazo.com/7b51794a6e5e474b508cf442ddebc8dc

我试图让它在击中它时从桨上反弹,我使用了这个代码:

boolean bounceInY = ball.getCenterY()+ ball.getRadius() > paddle.getTopLeftY();
boolean bounceInX = (ball.getCenterX()+ ball.getRadius() > paddle.getTopLeftX()) && (ball.getCenterX()+ ball.getRadius() < paddle.getTopLeftX() + paddle.getWidth());

if (bounceInY && bounceInX)
    ball.setDirectionY(UPWARDS);

我遇到的问题是它不一致,有时它会正确弹跳,有时它会在弹跳之前穿过桨叶,有时它会穿过桨叶但根本不会弹开。看起来像这样:https://gyazo.com/d1b5c848290fc23183c9b7296f757a51 我不确定我做错了什么,球从球拍上弹起的代码似乎对我有用。感谢您的帮助:)

检查弹跳的代码有点不对劲。首先,ball.getCenterX()+ball.getRadius() 实际上是球的右侧,这是您要与球拍位置进行比较的唯一部分。这意味着有效的球拍位置偏离了球的半径。您可以在图像中看到它 - 一旦球的最右侧与球拍对齐,球只会 "bounces"。

其次,即使更改了该部分,您的代码在某些情况下仍会失败。想象一下,例如,球在球拍的正下方,但还没有撞到墙上。假设您希望球继续向下移动直到撞到墙,然后向上弹回。但是,使用您现在拥有的代码,一旦球拍位于球上方,球将立即再次开始向上移动 - 根据您的布尔条件,球位于球拍下方并且 x 坐标位于球拍边缘之间,所以它应该 "bounce"。

我假设您是初学者并且可能不想学习大量数学知识,因此解决此问题的最简单方法是使用 AABB(轴对齐边界框)并测试使用该逻辑的碰撞。这是一个例子:

// I'm creating a bunch of variables here because I don't know
// what properties your objects have available.
int ballLeftSide     = ball.getCenterX() - ball.getRadius();
int ballRightSide    = ball.getCenterX() + ball.getRadius();
int ballTopSide      = ball.getCenterY() - ball.getRadius();
int ballBottomSide   = ball.getCenterY() + ball.getRadius();
int paddleLeftSide   = paddle.getTopLeftX();
int paddleRightSide  = paddle.getTopLeftX() + paddle.getWidth();
int paddleTopSide    = paddle.getTopLeftY();
int paddleBottomSide = paddle.getTopLeftY() + paddle.getHeight();

bool ballOverlapsPaddle = ((ballLeftSide < paddleRightSide) &&
                           (ballRightSide > paddleLeftSide) &&
                           (ballTopSide < paddleBottomSide) &&
                           (ballBottomSide > paddleTopSide))

// Only change ball direction if the ball hasn't already passed
// the paddle. In this case, "passed" means the ball's center is
// further down than the bottom of the paddle.
if ((ballOverlapsPaddle) && (ball.getCenter() < paddleBottomSide))
    ball.setDirectionY(UPWARDS);

检查重叠的布尔条件使用轴对齐边界框 (AABB) 的分离轴定理 (SAT) 的一种非常简单的形式。基本上,它检查两个矩形是否发生碰撞。由于您的形状之一是球,因此此方法在执行此检查时会将其视为周围有一个矩形边界框。

现在,虽然这个解决方案非常简单,但它确实带来了一些复杂的问题。由于您的球显然不是矩形,因此它的有效边界框会稍微超出球的实际形状。这意味着您将拥有 "collisions",即使在视觉上看起来没有任何东西,如下例所示。

当然有一些方法可以解决这个问题,但是对于问答形式来说,这有点过于详细和技术性了。如果你想自己研究一下,this is the tutorial 我在第一次学习形状之间的碰撞检测时使用过。