圆/矩形碰撞响应 [英] Circle/rectangle collision response

查看:109
本文介绍了圆/矩形碰撞响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我前段时间构建了一个 Breakout克隆,我想对其进行一些升级,主要用于碰撞.首次制作时,我在球和砖之间进行了基本的"碰撞"检测,实际上,该检测将球视为另一个矩形.但这造成了边缘碰撞的问题,所以我想我将对其进行更改.问题是,我找到了解决问题的答案:

So I built some time ago a little Breakout clone, and I wanted to upgrade it a little bit, mostly for the collisions. When I first made it I had a basic "collision" detection between my ball and my brick, which in fact considered the ball as another rectangle. But this created an issue with the edge collisions, so I thought I would change it. The thing is, I found some answers to my problem:

例如此图片

以及该线程的最后评论:圆形/矩形碰撞反应,但我找不到如何计算最终速度矢量.

and the last comment of this thread : circle/rect collision reaction but i could not find how to compute the final velocity vector.

到目前为止,我有:

-在矩形上找到了最近的点
-创建了法线和切向量

现在我需要以某种方式将速度矢量分为法向分量和切线分量;取反法向分量,并添加法线和切线分量以获得新的速度矢量",如果这看起来很抱歉非常简单,但是我无法解决这个问题... 代码:

And now what I need is to somehow "divide the velocity vector into a normal component and a tangent component; negate the normal component and add the normal and tangent components to get the new Velocity vector" I'm sorry if this seems terribly easy but I could not get my mind around that ... code :

function collision(rect, circle){
  var NearestX = Max(rect.x, Min(circle.pos.x, rect.x + rect.w));
  var NearestY = Max(rect.y, Min(circle.pos.y, rect.y + rect.w));

  var dist = createVector(circle.pos.x - NearestX, circle.pos.y - NearestY);
  var dnormal = createVector(- dist.y, dist.x);
//change current circle vel according to the collision response
}

谢谢!

也找到了,但我没有不知道它是否适用于矩形的所有点或仅适用于角.

Also found this but I didn't know if it is applicable at all points of the rectangle or only the corners.

推荐答案

用两张图最好地解释:

入射角=反射角.称这个值为θ.

Have angle of incidence = angle of reflection. Call this value θ.

θ=法线角-入射角.

atan2 是用于从x轴正方向计算矢量角度的函数

atan2 is the function for computing the angle of a vector from the positive x-axis.

然后,下面的代码将立即显示:

Then the code below immediately follows:

function collision(rect, circle){
  var NearestX = Max(rect.x, Min(circle.pos.x, rect.x + rect.w));
  var NearestY = Max(rect.y, Min(circle.pos.y, rect.y + rect.h));

  var dist = createVector(circle.pos.x - NearestX, circle.pos.y - NearestY);
  var dnormal = createVector(- dist.y, dist.x);

  var normal_angle = atan2(dnormal.y, dnormal.x);
  var incoming_angle = atan2(circle.vel.y, circle.vel.x);
  var theta = normal_angle - incoming_angle;
  circle.vel = circle.vel.rotate(2*theta);
}

另一种方法是获取沿切线的速度,然后从圆周速度中减去该值的两倍.

Another way of doing it is to get the velocity along the tangent and then subtracting twice this value from the circle velocity.

然后代码变成

function collision(rect, circle){
  var NearestX = Max(rect.x, Min(circle.pos.x, rect.x + rect.w));
  var NearestY = Max(rect.y, Min(circle.pos.y, rect.y + rect.h));

  var dist = createVector(circle.pos.x - NearestX, circle.pos.y - NearestY);
  var tangent_vel = dist.normalize().dot(circle.vel);
  circle.vel = circle.vel.sub(tangent_vel.mult(2));
}

以上两个代码段都在大约相同的时间(可能)基本上完成了相同的操作.只需选择您最了解的一个即可.

Both of the code snippets above do basically the same thing in about the same time (probably). Just pick whichever one you best understand.

此外,正如@arbuthnott指出的那样,存在复制粘贴错误,因为NearestY应该使用rect.h而不是rect.w.

Also, as @arbuthnott pointed out, there's a copy-paste error in that NearestY should use rect.h instead of rect.w.

修改:我忘记了位置分辨率.这是将两个物理对象分开以使其不再相交的过程.在这种情况下,由于块是静态的,因此我们只需要移动球即可.

Edit: I forgot the positional resolution. This is the process of moving two physics objects apart so that they're no longer intersecting. In this case, since the block is static, we only need to move the ball.

function collision(rect, circle){
  var NearestX = Max(rect.x, Min(circle.pos.x, rect.x + rect.w));
  var NearestY = Max(rect.y, Min(circle.pos.y, rect.y + rect.h));    
  var dist = createVector(circle.pos.x - NearestX, circle.pos.y - NearestY);

  if (circle.vel.dot(dist) < 0) { //if circle is moving toward the rect
    //update circle.vel using one of the above methods
  }

  var penetrationDepth = circle.r - dist.mag();
  var penetrationVector = dist.normalise().mult(penetrationDepth);
  circle.pos = circle.pos.sub(penetrationVector);
}

这篇关于圆/矩形碰撞响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆