首页 > 解决方案 > 检测圆形和方形之间的碰撞

问题描述

我知道这已经被问了很多,但就个人而言,我找不到合适的答案。几乎在任何地方,该函数看起来都像:

function rccol(rect, circle){
    var dx = Math.abs(circle.x - (rect.x + rect.width / 2));
    var dy = Math.abs(circle.y - (rect.y + rect.height / 2));

    if(dx > circle.radius + rect.width / 2) return false;
    if(dy > circle.radius + rect.height / 2) return false;

    if(dx <= rect.width) return true;
    if(dy <= rect.height) return true; 

    var dx = dx - rect.width;
    var dy = dy - rect.height
    return((dx * dx + dy * dy) <= (circle.radius * circle.radius));
}

这非常有效。问题是我在游戏中使用它进行碰撞检测,其中圆圈是玩家的碰撞框,而正方形是比方说一堵墙。我需要能够确定接触发生的位置,这样我才能真正防止“玩家”进入“墙”,因此返回的简单布尔值在我的用例中实际上不起作用。

标签: javascriptmathgeometryhtml5-canvascollision-detection

解决方案


有了圆心坐标(cx, cy),您可以计算从圆心到矩形的平方距离。

dx = Max(Abs(cx - rect.center.x) - rect.width / 2, 0)
dy = Max(Abs(cy - rect.center.y) - rect.height / 2, 0)
SquaredDistance = dx * dx + dy * dy

当圆形最初在矩形之外时,可以删除Max呼叫。

dx = Abs(cx - rect.center.x) - rect.width / 2
dy = Abs(cy - rect.center.y) - rect.height / 2

我们也可以删除Abs已知的初始位置(注意 - 直到符号更改的时刻!)

if cx >= rect.center.x:
      dx = cx - rect.center.x - rect.width / 2
else:
      dx =  - cx + rect.center.x - rect.width / 2

为了避免很多不同的情况,我们可以虚拟地将玩家放在相对于矩形中心的第一象限,并相应地改变坐标和速度分量

if cx0 < 0:
   cx0 = - cx0
   vx = -vx
if cy0 < 0:
   cy0 = - cy0
   vy = -vy

要记录碰撞时刻,您必须使用起点和速度矢量分量将坐标替换为参数方程(vx, vy)

cx = cx0 + vx * t
cy = cy0 + vy * t

并求解(二次)方程t

SquaredDistance - Radius^2 = 0

(cx0 + vx * t - rect.center.x - rect.width/2)^2 + 
(cy0 + vy * t - rect.center.y - rect.height/2)^2 - 
Radius^2 = 0

你可以得到零(无碰撞)、一个(触摸事件)或两个根(碰撞时刻和退出时刻)。


推荐阅读