我正在尝试重新制作 breakout,但我的球偶尔会完全跳过瓷砖,或者反弹不正确。我想我发现问题是我检测球是来自顶部、底部还是侧面的代码没有考虑到球的“步长”大小可以使它落在瓦。我尝试过的唯一防止这些错误发生的方法是减小步长,但这会使球移动得比我想要的慢。那么,我怎样才能保持球的速度不变,同时仍然准确地检测到它与哪一侧发生碰撞?
Vector2 ballCenter = new Vector2();
Vector2 tileCenter = new Vector2();
ballCenter = ball.getHitbox().getCenter(ballCenter);
tileCenter = tiles.get(i-1).getHitbox().getCenter(tileCenter);
if(ballCenter.y-ball.sprite.getHeight()/2>tileCenter.y){
ball.velocity.y = Math.max((-1*ball.velocity.y)+2,10);
}
else if(ballCenter.y+ball.sprite.getHeight()/2<tileCenter.y){
ball.velocity.y = Math.max((-1*ball.velocity.y)-1,-10);
}
else
ball.velocity.x *=-1;
最佳答案
从外观上看,您的代码会检测到在步骤发生时球当前是否正在与方 block 碰撞。问题是,除非你的步长非常小,否则碰撞在正确的时间恰好与步长重合的可能性很小。由于您在步骤之间发生了碰撞,因此您会遇到像球跳过瓷砖并完全忽略它们这样的事情。
对此的一种解决方案是更改您进行碰撞检测的方式。您不需要检查球是否在此时击中了方 block ,而是需要检查球是否在当前步骤和前一步之间的任何时间点击中了方 block 。
由于您同时拥有球的位置和速度,并且我假设是静态图 block ,因此您可以将其建模为找到从球的旧位置到球的新位置(旧位置)的线的交点+ 假设没有碰撞的速度)。
然后,如果存在交集(碰撞),您可以采用更复杂的处理。
所以,伪代码看起来像这样:
// use some basic geometry to find intersections between the ball's motion vector
// and the tiles bounding square
if (isCollision(ball, tile))
{
// If there is a collision then find out how far through the step it occurred
// i.e.: 0 = start, 1 = end, 0.5 = half way through
collision_time = findCollisionTime(ball, tile);
//process the part of the step before the collision
ball.x = ball.x + (ball.velocity.x * collision_time);
ball.y = ball.y + (ball.velocity.y * collision_time);
//or however you want to do it.
//update the velocity to for the collision
ball.velocity.x = ...
ball.velocity.y = ...
//process the part of the step after the collision
ball.x = ball.x + (ball.velocity.x * (1-collision_time));
ball.y = ball.y + (ball.velocity.y * (1-collision_time));
}
注意:我在上面展示的方法假设只有球在移动,并且它永远不会在一个步骤中与多个方 block 碰撞。它应该很容易允许通过一些适应和 while 循环进行多次碰撞。允许非静态碰撞需要更多思考。
或者,您可以研究物理引擎来为您完成所有这些工作。
关于java - 如何检测侧面碰撞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21816000/