实际上我试图在下面的代码中检测Rectangle与圆圈的碰撞: -
function checkCollision() {
//checking of the Collision
if (ry + rh > cy - radius && rx + rw > cx - radius && rx + rw < cx + radius ) {
dy = -dy;
}
}
这也是我的代码的一部分: -
var rx = 50; //distance from the x-axis of the Rect.
var ry = 50; //distance from the y-axis of the Rect.
var rw = 80; //width of the Rect
var rh = 30; //Height of the Rect.
// Distance to moved of the Rect.
var dx = 2;
var dy = 2;
// Center of the circle from the x-axis and y-axis.
var cx = 105;
var cy = 135;
var radius = 16;
var cx1 = 6;
var cy1 = 6;
任何人都可以帮助我找出问题所在吗?
答案 0 :(得分:38)
检测圆形碰撞并非易事(但也不是那么复杂)。
@kuroi neko的解决方案是正确的,就像代码一样简单。
幸运的是,您不需要完全理解使用命中测试功能的数学理论。
如果您确实需要有关该功能如何工作的更多详细信息,请按以下步骤使用4个步骤测试圆形和矩形是否发生碰撞:
演示:http://jsfiddle.net/m1erickson/n6U8D/
首先,定义一个圆圈和一个矩形
var circle={x:100,y:290,r:10};
var rect={x:100,y:100,w:40,h:100};
第1步:找到纵向&amp;圆的中心和矩形的中心之间的水平(distX / distY)距离
var distX = Math.abs(circle.x - rect.x-rect.w/2);
var distY = Math.abs(circle.y - rect.y-rect.h/2);
步骤2:如果距离大于halfCircle + halfRect,那么它们相距太远而不会发生碰撞
if (distX > (rect.w/2 + circle.r)) { return false; }
if (distY > (rect.h/2 + circle.r)) { return false; }
步骤3:如果距离小于halfRect,那么它们肯定会发生碰撞
if (distX <= (rect.w/2)) { return true; }
if (distY <= (rect.h/2)) { return true; }
步骤4:测试矩形角落的碰撞。
使用毕达哥拉斯公式来比较圆和直中心之间的距离。
var dx=distX-rect.w/2;
var dy=distY-rect.h/2;
return (dx*dx+dy*dy<=(circle.r*circle.r));
下面是完整的代码:
var circle={x:100,y:290,r:10};
var rect={x:100,y:100,w:40,h:100};
// return true if the rectangle and circle are colliding
function RectCircleColliding(circle,rect){
var distX = Math.abs(circle.x - rect.x-rect.w/2);
var distY = Math.abs(circle.y - rect.y-rect.h/2);
if (distX > (rect.w/2 + circle.r)) { return false; }
if (distY > (rect.h/2 + circle.r)) { return false; }
if (distX <= (rect.w/2)) { return true; }
if (distY <= (rect.h/2)) { return true; }
var dx=distX-rect.w/2;
var dy=distY-rect.h/2;
return (dx*dx+dy*dy<=(circle.r*circle.r));
}
答案 1 :(得分:5)
这是一种方法:
1)找到最接近圆心的矩形角 2)看看圆圈相对于角落的位置
该函数采用第三个参数来区分“实心”矩形和简单轮廓(即,完全位于矩形内部的圆形是否应视为碰撞)
function collides (rect, circle, collide_inside)
{
// compute a center-to-center vector
var half = { x: rect.w/2, y: rect.h/2 };
var center = {
x: circle.x - (rect.x+half.x),
y: circle.y - (rect.y+half.y)};
// check circle position inside the rectangle quadrant
var side = {
x: Math.abs (center.x) - half.x,
y: Math.abs (center.y) - half.y};
if (side.x > circle.r || side.y > circle.r) // outside
return false;
if (side.x < -circle.r && side.y < -circle.r) // inside
return collide_inside;
if (side.x < 0 || side.y < 0) // intersects side or corner
return true;
// circle is near the corner
return side.x*side.x + side.y*side.y < circle.r*circle.r;
}
var rect = { x:50, y:50, w:80, h:30 };
var circle = { x:105, y:135, r:16 };
if (collides (rect, circle)) { /* bang! */ }
我有第二个函数来计算碰撞法线向量,以允许动画一个圆形弹跳矩形。 它们共同作为this fiddle
的基础function bounces (rect, circle)
{
// compute a center-to-center vector
var half = { x: rect.w/2, y: rect.h/2 };
var center = {
x: circle.x - (rect.x+half.x),
y: circle.y - (rect.y+half.y)};
// check circle position inside the rectangle quadrant
var side = {
x: Math.abs (center.x) - half.x,
y: Math.abs (center.y) - half.y};
if (side.x > circle.r || side.y > circle.r) // outside
return { bounce: false };
if (side.x < -circle.r && side.y < -circle.r) // inside
return { bounce: false };
if (side.x < 0 || side.y < 0) // intersects side or corner
{
var dx = 0, dy = 0;
if (Math.abs (side.x) < circle.r && side.y < 0)
{
dx = center.x*side.x < 0 ? -1 : 1;
}
else if (Math.abs (side.y) < circle.r && side.x < 0)
{
dy = center.y*side.y < 0 ? -1 : 1;
}
return { bounce: true, x:dx, y:dy };
}
// circle is near the corner
bounce = side.x*side.x + side.y*side.y < circle.r*circle.r;
if (!bounce) return { bounce:false }
var norm = Math.sqrt (side.x*side.x+side.y*side.y);
var dx = center.x < 0 ? -1 : 1;
var dy = center.y < 0 ? -1 : 1;
return { bounce:true, x: dx*side.x/norm, y: dy*side.y/norm };
}
答案 2 :(得分:2)
碰撞检测的近似版本,假设圆实际上是正方形。如果圆圈足够小,则用户不会注意到差异。
如果从中心绘制矩形:
if(sphere.x + sphere.radius > (rectangle.x - rectangle.width / 2) &&
sphere.x - sphere.radius < (rectangle.x + rectangle.width / 2) &&
sphere.y + sphere.radius > (rectangle.y - rectangle.height / 2) &&
sphere.y - sphere.radius < (rectangle.y + rectangle.height / 2))
{
//collided
}
如果从左上角绘制矩形:
if(sphere.x + sphere.radius > rectangle.x &&
sphere.x - sphere.radius < (rectangle.x + rectangle.width) &&
sphere.y + sphere.radius > rectangle.y &&
sphere.y - sphere.radius < (rectangle.y + rectangle.height))
{
//collided
}
这是两个版本的jsfiddle: https://jsfiddle.net/TappT/z5r21nu0/16/
答案 3 :(得分:0)
我发现我遇到了所选答案的问题。我觉得这很好,我认为效果很好:
function collisionCheckCircleRect(circle, rect)
{
var distx = Math.abs(circle.x - rect.x);
var disty = Math.abs(circle.y - rect.y);
if (distx > (rect.width/2 + circle.radius)) { return false; }
if (disty > (rect.height/2 + circle.radius)) { return false; }
if (distx <= (rect.width/2)) { return true; }
if (disty <= (rect.height/2)) { return true; }
var hypot = (distx - rect.width/2)*(distx- rect.width/2) +
(disty - rect.height/2)*(disty - rect.height/2);
//console.log(hypot <= (circle.radius*circle.radius))
return (hypot <= (circle.radius*circle.radius));
}