JS Arkanoid 碰撞检测(侧面与底部和顶部)
JS Arkanoid collision detection (sides vs bottom and top)
我知道有很多线程有类似的问题,我已经阅读并尝试了其中的许多线程,但仍然无法得到我想要的结果。也许有人可以帮助我。
我正在编写一个 JS 打砖块(Breakout)类型的游戏来提高我的 JS 技能,但我在碰撞检测方面遇到了一些问题。与桨或墙壁的碰撞有效,但与砖块的碰撞无效。
球和砖块是 类 球和砖块的实例,每个都有自己的实例
pos: {
x: ...
y: ...
}
球从中心(using ball.pos.x
和 ball.pos.y
)开始,半径为 ball.r
。球也有 x 和 y 速度(ball.vel.x
和 ball.vel.y
)。
砖块是从左上角绘制的(brick.pos.x
和 brick.pos.y
),它们有高度(brick.h
)和宽度(brick.w
)。我还为砖块添加了一个中心点(brick.center.x
和 brick.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;
}
}
其中 xDist
和 yDist
现在是球和砖块最近边缘之间的绝对距离(在砖块最近的角相交)。您现在不仅可以使等式适用于圆球:
xDist < ball.r && yDist < 0 || yDist < ball.r && xDist < 0 || xDist**2 + yDist**2 < ball.r**2
还可以通过xDist
和yDist
之间的比例来区分边:
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;
}
我知道有很多线程有类似的问题,我已经阅读并尝试了其中的许多线程,但仍然无法得到我想要的结果。也许有人可以帮助我。
我正在编写一个 JS 打砖块(Breakout)类型的游戏来提高我的 JS 技能,但我在碰撞检测方面遇到了一些问题。与桨或墙壁的碰撞有效,但与砖块的碰撞无效。
球和砖块是 类 球和砖块的实例,每个都有自己的实例
pos: {
x: ...
y: ...
}
球从中心(using ball.pos.x
和 ball.pos.y
)开始,半径为 ball.r
。球也有 x 和 y 速度(ball.vel.x
和 ball.vel.y
)。
砖块是从左上角绘制的(brick.pos.x
和 brick.pos.y
),它们有高度(brick.h
)和宽度(brick.w
)。我还为砖块添加了一个中心点(brick.center.x
和 brick.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;
}
}
其中 xDist
和 yDist
现在是球和砖块最近边缘之间的绝对距离(在砖块最近的角相交)。您现在不仅可以使等式适用于圆球:
xDist < ball.r && yDist < 0 || yDist < ball.r && xDist < 0 || xDist**2 + yDist**2 < ball.r**2
还可以通过xDist
和yDist
之间的比例来区分边:
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;
}