JS Arkanoid 碰撞检测(侧面与底部和顶部)

JS Arkanoid collision detection (sides vs bottom and top)

我知道有很多线程有类似的问题,我已经阅读并尝试了其中的许多线程,但仍然无法得到我想要的结果。也许有人可以帮助我。

我正在编写一个 JS 打砖块(Breakout)类型的游戏来提高我的 JS 技能,但我在碰撞检测方面遇到了一些问题。与桨或墙壁的碰撞有效,但与砖块的碰撞无效。

球和砖块是 类 球和砖块的实例,每个都有自己的实例

pos: {
    x: ...
    y: ...
}

球从中心(using ball.pos.xball.pos.y)开始,半径为 ball.r。球也有 x 和 y 速度(ball.vel.xball.vel.y)。

砖块是从左上角绘制的(brick.pos.xbrick.pos.y),它们有高度(brick.h)和宽度(brick.w)。我还为砖块添加了一个中心点(brick.center.xbrick.center.y)。

在球的更新函数中,我像这样检查与每块砖的碰撞:

for (let i = 0; i < bricks.length; i++) {
    let collision = detectCollision(this, bricks[i]);
}

并且检测碰撞是

function detectCollision(ball, brick) {
    let xDist = calculateDistance(ball.pos.x, brick.center.x);
    let yDist = calculateDistance(ball.pos.y, brick.center.y);

if (xDist < (ball.r + brick.w / 2) && yDist < (ball.r + brick.h / 2)) {
    return true;
} else {
    return false;
}

function calculateDistance(pointA, pointB) {
    return Math.abs(pointA - pointB);
}

我现在知道代码实际上没有做任何事情。我只是将它存储在 collision 变量中。这只是为了告诉你我的想法是什么。我可以用这个功能检测球和砖块是否碰撞,但不能检测球与哪一侧碰撞。

我现在遗漏而且似乎无法理解的是如何检测碰撞是与顶部、底部还是其中一侧发生的。如果碰撞发生在顶部或底部,我必须翻转 ball.vel.y,如果碰撞发生在其中一侧,我必须翻转 ball.vel.x.

我会从

开始
function detectCollision(ball, brick) {
    let xDist = calculateDistance(ball.pos.x, brick.center.x) - brick.w / 2;
    let yDist = calculateDistance(ball.pos.y, brick.center.y) - brick.h / 2;

    if (xDist < ball.r && yDist < ball.r) {
        return true;
    } else {
        return false;
    }
}

其中 xDistyDist 现在是球和砖块最近边缘之间的绝对距离(在砖块最近的角相交)。您现在不仅可以使等式适用于圆球:

xDist < ball.r && yDist < 0 || yDist < ball.r && xDist < 0 || xDist**2 + yDist**2 < ball.r**2

还可以通过xDistyDist之间的比例来区分边:

if (/* collides */) {
    if (xDist < yDist)
        return "vertical"; // from top or bottom
//  else if (xDist == yDist)
//      return "45°";
    else
        return "horizontal"; // from left or right
} else {
    return null;
}