Java 碰撞响应法

Java 碰撞响应法,java,math,graphics,game-development,Java,Math,Graphics,Game Development,嗨,我尝试实现一个简单的球体碰撞检测算法,如下所述: 因此,我实现了检查是否发生碰撞的方法: private boolean advancedSphereSphere(Sphere a, Sphere b) { Vector2D s = a.getPos().sub(b.getPos()); Vector2D v = a.getVelocity().sub(b.getVelocity()); float r = a.getRadius() + b.getRadius(); double c

嗨,我尝试实现一个简单的球体碰撞检测算法,如下所述:

因此,我实现了检查是否发生碰撞的方法:

private boolean advancedSphereSphere(Sphere a, Sphere b) {

Vector2D s = a.getPos().sub(b.getPos());
Vector2D v = a.getVelocity().sub(b.getVelocity());

float r = a.getRadius() + b.getRadius();

double c1 = s.dot(s) - r*r;

if(c1 < 0.0) {
    timeToCollision = .0f;
    return true;
}

double a1 = v.dot(v);
if(a1 < 0.00001f) {
    return false;
}

double b1 = v.dot(s);
if(b1 >= 0.0) {
    return false;
}

double d1 = b1*b1 - a1*c1;
if(d1 < 0.0) {
    return false;
}

timeToCollision = (float) (-b1 - Math.sqrt(d1) / a1);

return true;
}
问题出现在flowPhysicsboolean方法中,在这一行:

for(int i=0; i < mSpheres.size(); ++i) {
            for(int j=i+1; j < mSpheres.size(); ++j) {

                Sphere a = mSpheres.get(i);
                Sphere b = mSpheres.get(j);

                if(advancedSphereSphere(a, b) || step) {
                    if(timeToCollision < dt && !step) {
                        flowPhysics(true);
                    }

                    if(step) {
                        sphereCollisionResponse(a, b);
                    }
                }

            }
        }
如果我把其他的东西放在这里,不从a向量中减去b,它会画出球,但不会发生碰撞。上面的Java代码主要是从这里移植的代码:

你能告诉我问题出在哪里吗

谢谢

更新


如果问题真的在这方面

Vector2D s = a.getPos().sub(b.getPos());
那么我怀疑问题可能出在Vector2D类中。您应该检查sub方法是否只返回一个新的Vector2D,并且不修改原始向量a的坐标。尽可能使对象保持不变,这样使用起来更安全

如果做不到这一点,答案是。从长远来看,学会使用或将获得回报,但即使是一些特别的打印语句,现在也可能对您有所帮助。您应该能够独立于球体在屏幕上的显示方式来检查数学是否正确,并且始终如一地这样做可能会引导您实现更清晰的设计

只要测试碰撞后每个球体的位置保持不变,并且在一些简单的情况下,速度与预期一致,就很可能在代码中发现错误。例如,如果两个速度之前都为零,那么之后它们应该为零。如果碰撞是弹性的,并且一个球体A与另一个静止的球体B迎面碰撞,那么球体A在碰撞之后应该是静止的,球体B应该具有A开始时的速度

我没有在你的代码中检查数学,但是当我设置一些简单的类来填充依赖项并给它一些合理的启动条件时,它并没有保持动量,所以我可以相信,对于某些值,球最终可能会以光速飞离屏幕


一旦你掌握了正确的物理知识,你就可以在知道问题确实存在的情况下,通过球体的显示来解决任何剩余的问题。

第一个球体消失了,这是因为你的系统认为它与自身发生了碰撞吗?doPhysics和sphereCollisionResponse做什么?步骤定义在哪里?它是如何定义的?步骤是flowPhysicsboolean步骤中的参数,就像递归工作的助手一样。在onDraw中,正如您所看到的,我有flowPhysicsfalse,然后我有flowPhysics本身的递归,如果发生冲突,我将其设置为true flowPhysicstrue.Hi。子方法中存在错误-是。但是再一次,碰撞效果很好,然后反应就不起作用了。您可以检查以下代码以获得响应吗:-我使用此Vector2D类:。当球碰撞时-第一个a-消失:我稍后会检查代码,但在快速查看Vector2D后,我认为您希望使用减法而不是sub来避免修改原始向量。你的球可能会跳到屏幕外的某个位置,这可能会使它看起来消失。是的-我改为减法-但它仍然会从我的屏幕上跳下来:
Vector2D s = a.getPos().sub(b.getPos());
private void sphereCollisionResponse(Sphere a, Sphere b)
    {
        double m1, m2, x1, x2;
        Vector2D v1, v2, v1x, v2x, v1y, v2y;
        Vector2D x = new Vector2D(a.getPos().sub(b.getPos()));

        x.normalize();
        v1 = new Vector2D(a.getVelocity());
        x1 = x.dot(v1);
        v1x = new Vector2D(x.multiply(x1));
        v1y = new Vector2D(v1.sub(v1x));
        m1 = a.getMass();

        x = new Vector2D(x.multiply(-1));
        v2 = new Vector2D(b.getVelocity());
        x2 = x.dot(v2);
        v2x = new Vector2D(x.multiply(x2));
        v2y = new Vector2D(v2.sub(v2x));
        m2 = b.getMass();

        Vector2D nn = new Vector2D(v1x.multiply(m1-m2));
        Vector2D mm = new Vector2D(nn.divide(m1+m2));
        Vector2D tt = new Vector2D(v2x.multiply(2*m2));
        Vector2D rr = new Vector2D(tt.divide(m1+m2));
        Vector2D gg = new Vector2D(mm.add(rr));
        Vector2D ss = new Vector2D(gg.add(v1y));

        Vector2D nva = ss; 
        a.setVelocity(nva);

        Vector2D nvb = new Vector2D(v1x.multiply(2*m1).divide(m1+m2).add(v2x.multiply(m2-m2).divide(m1+m2).add(v2y)));
        b.setVelocity(nvb);     
} 
Vector2D s = a.getPos().sub(b.getPos());