【问题标题】:Javascript - Circle-Circle Collision IssueJavascript - 圆-圆碰撞问题
【发布时间】:2014-05-20 02:50:00
【问题描述】:

我正在用 HTML5 Canvas 制作游戏,这是我解决两个移动圆之间碰撞的代码:

function resCCCol(a, b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;

    var dist = dx * dx + dy * dy;

    var vx = b.vx - a.vx;
    var vy = b.vy - a.vy;

    var dot = dx * vx + dy * vy;

    if (dot > 0) {
        var scale = dot / dist;

        var cx = dx * scale;
        var cy = dy * scale;

        var mass = a.r + b.r;

        var cw1 = 2 * b.r / mass;
        var cw2 = 2 * a.r / mass;

        a.vx += cw1 * cx
        a.vy += cw1 * cy
        b.vx -= cw2 * cx
        b.vy -= cw2 * cy
    }
}

如果我将坐标设置为使圆圈重叠但它们的速度仍为 0,则圆圈不会相互推出,这就是问题所在。我该如何解决这个问题?

编辑:小提琴:http://jsfiddle.net/yP7xf/2/,点击“小故障!”看到故障,因为你看到它们不会分开。

【问题讨论】:

  • 请做一个小提琴。
  • 如果您添加一些 cmets 来说明您的代码,将会有所帮助。但总的来说,如果两个圆重叠但速度为零,您希望它们做什么?它们必须在弹跳之前移动,否则将无法计算新的速度。最好先确保他们不会进入那种状态。
  • 离题但有一个技巧可以根据阈值检查距离并避免平方根。你知道如果sqrt(x) < y 那么x < y*y。在您的情况下,您可以检查dx*dx+dy*dy <= (a.r+b.r)*(a.r+b.r)。您还可以预先计算 (a.r+b.r)*(a.r+b.r) 并且仅在其中一个半径发生变化时更新它,然后距离测试非常快(2 次乘法、1 次加法和比较 --dx*dx+dy*dy <= a_plus_b_squared)。
  • 至于你的问题;你能更详细地描述你试图获得的确切行为吗?

标签: javascript html canvas physics collision


【解决方案1】:

我不确定dot 的用途是什么(也许我在这里缺少一些数学知识),但是如果dist < sum(radii) 会发生两个圆圈碰撞。如果发生这种情况,您应该使圆圈偏转,但要确保它们至少有一些小速度以确保它们分开。

【讨论】:

  • 你如何确保这一点?
  • 嗯,你有水平和垂直速度,也许检查它们是否都为零,如果是,请调整它们以使圆圈彼此远离?
  • 难道没有办法把它们放在彼此的外面吗?
  • 您可以确定将它们分开的方向,sum(radii)-dist 是移动它们的距离(合并,所以也许/2 每个?)
  • 虽然我不确定当两个物体以零速度开始相互交叉时有多少物理可以帮助......
【解决方案2】:

当两个圆圈没有速度重叠时,您的resCCCol() 方法将不起作用,因为dot0。即使您将if 语句更改为在dot >= 0 上执行,您的速度仍然为0。

if (dot > 0) { //dot === 0
    var scale = dot / dist; //scale === 0

    var cx = dx * scale; //cx === 0
    var cy = dy * scale; //cy === 0

    var mass = a.r + b.r;

    var cw1 = 2 * b.r / mass;
    var cw2 = 2 * a.r / mass;

    a.vx += cw1 * cx // 0
    a.vy += cw1 * cy // 0
    b.vx -= cw2 * cx // 0
    b.vy -= cw2 * cy // 0
}

你应该处理dot === 0 的情况。最简单的方法是在速度为0 时简单地给它们一个设定速度:

if (dot > 0) { 
    ... 
} else {
    a.vx = 1;
    a.vy = 1;
    b.vx = -1;
    b.vy = -1;
}

当然,这只会将它们彼此推向屏幕的相对角落,但您可以轻松实现更符合物理定律的东西(忽略两个对象不能占据相同的空间)。

【讨论】:

  • 我的意思是快速移动他们的位置,而不是增加速度。
  • 两个圆的速度仍然是0,所以这行不通。
  • 不,我的意思是把它们放在彼此之外,如果它们在彼此之间的话,就通过它们的坐标和距离角度来区分
  • 如果您不希望它们偏转,那肯定会起作用。你的问题并不完全清楚,如果这是你得到的结论。我们只是来帮助编写代码,但物理学不一定是我们的强项。
  • 我们的意思是什么?
【解决方案3】:

目前尚不完全清楚处理此问题的最佳方法是什么,我认为最好首先确保您不会陷入这种情况(确保它们永远不会重叠速度为零),但一个快速而肮脏的解决方法是检查dot === 0,如果是,给他们一些速度。例如:

if (dot === 0) {
    // numbers pulled completely out of thin air...
    a.vx = 0.5;
    a.vy = 0.5;
    b.vx = -0.5;
    b.vy = -0.5;
}

http://jsfiddle.net/yP7xf/5/

现在你应该给他们什么速度?这是你需要解决的问题。可能您希望它们分开,因此您可能可以根据从一个中心到另一个中心的线计算某个向量,并以您认为的任何速度沿该向量向一个方向发送一个,另一个在另一个方向发送合适的。但如果它们完全重叠放置(中心在同一点),那么您也需要考虑这种情况。

【讨论】:

  • imgur.com/yEFbUdL,难道没有让它们完全远离彼此而不是增加速度,只需将位置设置在另一个之外?
  • @Murplyx Math.atan2(b.y - a.y, b.x - a.x); 会给你以弧度表示的角度(所以你可以使用Math.cosMath.sin)。
  • @Murplyx:当然,只需计算从一个中心到另一个中心的线,然后沿着这条线移动它们,直到它们不再重叠。但这是一个三角问题,我太生疏了,不能一时兴起。
  • @Murplyx:正如我所说,太生疏了。这个在你身上。
  • 那么有没有不使用三角函数的,它很贵?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 2022-09-25
  • 1970-01-01
相关资源
最近更新 更多