2

这是一个简短的视频,其中可以看到两个(可能更多)粒子组相互干扰。

源代码可以在这里找到。

这是我用来计算碰撞的代码:

function collisionPhysics()
{
    for (var i = 0; i < N - 1; ++i)
    {
        for (var j = i + 1; j < N; ++j)
        {
            var Dx = objects[j].x - objects[i].x;    // Difference in X direction between objects[i] and objects[j].
            var Dy = objects[j].y - objects[i].y;    // Difference in Y direction between objects[i] and objects[j].
            var D2 = Dx * Dx + Dy * Dy;              // Distance between objects[i] and objects[j] squared.

            if (D2 <= (objects[i].rad + objects[j].rad) * (objects[i].rad + objects[j].rad))    // Colision check could be inserted here, reusing D2.
            {
                var delta = 2 * (Dx * (objects[i].Vx - objects[j].Vx) + Dy * (objects[i].Vy - objects[j].Vy)) / (D2 * (objects[i].m + objects[j].m));
                objects[i].Vx += -objects[i].m * delta * Dx;
                objects[i].Vy += -objects[i].m * delta * Dy;
                objects[j].Vx +=  objects[j].m * delta * Dx;
                objects[j].Vy +=  objects[j].m * delta * Dy;
            }
        }
    }
}

编辑 2013/04/06: nwellcome 提到的问题导致了奇怪的行为。这个调整后的功能应该可以解决这个问题,不确定它是否可以提高性能,但它可以工作:

function collisionPhysics()
{
    for (var i = 0; i < N - 1; ++i)
    {
        for (var j = i + 1; j < N; ++j)
        {
            var Dx = objects[j].x - objects[i].x + timeStep * (objects[j].u - objects[i].u);
            var Dy = objects[j].y - objects[i].y + timeStep * (objects[j].v - objects[i].v);
            var D2 = Dx * Dx + Dy * Dy;              // Distance between objects[i] and objects[j] squared.

            if (D2 <= (objects[i].r + objects[j].r) * (objects[i].r + objects[j].r))    // Colision check could be inserted here, reusing D2.
            {
                objects[i].col = true;
                objects[j].col = true;
                var dx = objects[j].x - objects[i].x;
                var dy = objects[j].y - objects[i].y;
                var du = objects[j].u - objects[i].u;
                var dv = objects[j].v - objects[i].v;
                var dr = objects[j].r + objects[i].r;
                var dt = (-Math.sqrt(2 * dx * du * dy * dv - du * du * (dy * dy - dr * dr) - dv * dv * (dx * dx - dr * dr)) - dx * du - dy * dv) / (du * du + dv * dv);
                Dx = objects[j].x - objects[i].x + dt * (objects[j].u - objects[i].u);
                Dy = objects[j].y - objects[i].y + dt * (objects[j].v - objects[i].v);
                D2 = Dx * Dx + Dy * Dy;
                var delta = 2 * (Dx * (objects[i].u - objects[j].u) + Dy * (objects[i].v - objects[j].v)) / (D2 * (objects[i].m + objects[j].m));
                objects[i].u += -objects[i].m * delta * Dx;
                objects[i].v += -objects[i].m * delta * Dy;
                objects[j].u +=  objects[j].m * delta * Dx;
                objects[j].v +=  objects[j].m * delta * Dy;
                objects[i].x += (timeStep - dt) * objects[i].u;
                objects[i].y += (timeStep - dt) * objects[i].v; 
                objects[j].x += (timeStep - dt) * objects[j].u;
                objects[j].y += (timeStep - dt) * objects[j].v;
            }
        }
    }
}
4

1 回答 1

0

问题是您的碰撞解决方法不能确保粒子在下一帧开始时仍不会相交。

当你发现碰撞时,你需要回溯到粒子边界发生碰撞的时间点,并从那里解决碰撞。有关执行此操作的方法,请参阅此游戏开发对类似问题的回答。

于 2013-04-05T15:26:07.143 回答