球有时弹跳有时不会

时间:2015-09-23 18:15:34

标签: java animation collision-detection bounce

此代码使球在画布周围反弹:

//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我不确定我做错了什么,球从球拍上反弹的代码似乎应该对我有用。任何帮助表示赞赏:)

1 个答案:

答案 0 :(得分:2)

检查弹跳的代码稍微关闭了。首先,ball.getCenterX()+ball.getRadius()实际上是球的右侧,而且这是您与球拍位置进行比较的唯一部分。这意味着有效桨叶位置偏离的量等于球的半径。你可以在你的形象中看到它 - 只有球#34;反弹&#34;一旦球的最右侧与桨对齐。

其次,即使更改了该部分,您的代码仍会在某些条件下失败。想象一下,例如,球直接在桨下但尚未撞到墙上。据推测,你希望球继续向下移动直到它撞到墙壁,然后向上弹回。但是,根据您现在拥有的代码,只要球拍在球的上方,球就会立即再次向上移动 - 根据您的布尔条件,球在球拍下方且x坐标在球拍之间&# 39; s边缘,所以它应该&#34;反弹&#34;。

我假设您是初学者并且可能不想进入大量数学,因此解决此问题的最简单方法是使用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);

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

现在,虽然这个解决方案非常简单,但它确实带来了一些复杂性。由于你的球显然不是一个矩形,它的有效边界框将延伸超出球的实际形状。这意味着你将发生碰撞&#34;即使在视觉上看起来没有任何东西,如下例所示。

False positive "collision"

当然有解决这个问题的方法,但对于Q + A格式来说,这有点过于细致和技术性。如果您想自己查看,this is the tutorial我在第一次了解到形状之间的碰撞检测时就习惯了。