0

这是有问题的代码:

public void calculate() {
        // Center of circle is at (250, 250).
        //THIS ALGORITHM IS NOW PROVEN TO BE WORSE THAN I FEARED...

        /*      What it does:
         *          Moves object around in a circle.
         *          Does not move the object towards the center.
         *          Object always stays on the rim of the circle.
         * 
         *      Algorithm I used. (DOES NOT WORK):
         *          N is normalized vector. 
         *          R = -2*(V dot N)*N + V
         */

        vx += Accelero.X * 0.1;
        vy += Accelero.Y * 0.1;
        double nx = x - 250;
        double ny = y - 250;
        double nd = Math.hypot(nx, ny);
        if (nd == 0)
            nd = 1;
        nx /= nd;
        ny /= nd;
        double dotProduct = vx * nx + vy * ny;
        vx += (float) (-2 * dotProduct * nx);
        vy += (float) (-2 * dotProduct * ny);
        x -= vx * 2;
        y -= vy * 2;
        vx *= 0.99;
        vy *= 0.99;
    }

这就是发生的事情。

图片。

您看到的黑线是紫色对象(框)移动的位置。它恰好正好在我画的圆线上Canvas.drawCircle()

我不明白为什么反射不起作用。如果一个物体要撞到圆形墙上,它不应该反映物体的速度方向,这就是算法的本意吗?还是我使用了错误的算法?

任何帮助表示赞赏。提前致谢。

4

3 回答 3

2

你能从任意角度的直墙上反弹吗?这应该是第一步。(您可能会发现速度矢量的极坐标表示更易于使用。)

一旦你完成了这项工作,它应该相当简单:从一个圆反弹就像从一个在接触点接触它的圆的切线反弹。

您可以通过观察它垂直于接触点中的半径矢量(即从对象所在位置到圆心的矢量)来计算此切线

于 2012-08-20T15:38:13.153 回答
2

是否有基于矢量的实现,而不依赖于角度?

是的,请参阅2-Dimensional Elastic Collisions without Trigonometry,如图所示KineticModel。您的实现似乎缺少切向组件。详情请参阅Ensemble#collideAtoms()

于 2012-08-20T15:53:28.763 回答
1

这就是我所拥有的,我将与大家分享我的发现。

public void calculate() {
    // Center of circle is at (250, 250). Radius is 40.
    //THIS ALGORITHM IS PROVEN TO BE BETTER THAN I FEARED...

    /*      What it does:
     *          Moves object around in a circle, if object is 
     *              inside of circle.
     *          Does not move the object towards the center, 
     *              nor outwards. This is crucial.
     *          Object always stays on the rim of the circle, 
     *              if the collision detection allows it to.
     * 
     *      Algorithm I used. (DOES WORK, NOT EXPECTING THIS THOUGH.):
     *          N is normalized vector. 
     *          R = -2*(V dot N)*N + V
     */



    double nx = x - 250;
    double ny = y - 250;
    double nd = Math.hypot(nx, ny);
    if (nd < 40){
        vx += Accelero.X * 0.1;
        vy += Accelero.Y * 0.1;
        x -= vx;
        y -= vy;
        vx *= 0.9;
        vy *= 0.9;
        return;
    }

    vx += Accelero.X * 0.1;
    vy += Accelero.Y * 0.1;


    if (nd == 0)
        nd = 1;
    nx /= nd;
    ny /= nd;
    double dotProduct = vx * nx + vy * ny;
    vx += (float) (-2 * dotProduct * nx);
    vy += (float) (-2 * dotProduct * ny);
    x -= vx * 2;
    y -= vy * 2;
    vx *= 0.99;
    vy *= 0.99;
}

我在我的函数中嵌入了一个碰撞检测,基本上使这个函数尽可能地不高效。忽略这一点,因为它不是主要焦点。

圆的半径为 40,(x,y) 位置为 (250,250)。

只有当物体在圆上,或者远离圆心时,我们才应该计算碰撞响应,由算法 R = -2*(V dot N)*N + V 给出,其中法向量N 已经归一化。

该算法确实是正确的,我的碰撞检测的布尔条件是导致对象停留在圆的边缘并在圆上绕圈的原因。

我没有说@trashgod 提供的另一种算法是错误的。这是因为一些奇怪的问题导致对象异常移动。我猜这是我使用的 API 的错,它不允许双打,但我可能不正确。我只是找不到问题的根源。我也很高兴不再进一步研究它。

碰撞检测布尔条件本身可以改变一切,只要稍微改变一下。如果不是@nm 指出我似乎忘记了一个减号(在这种情况下是一个非符号),我可能永远不会意识到它是多么微不足道。

于 2012-08-21T10:58:11.863 回答