物理圈碰撞弹出并滑向界限

时间:2016-02-27 15:49:41

标签: java physics collision

在Java中,我正在为Android编写一个移动应用程序,以便与我自己编写的某些类进行交互。重力取决于手机的倾斜度。

我注意到当我在一个角落里蜷缩成一堆球时,其中一些会开始抖动,或者有时会在与其他球碰撞时滑动。这可能是因为我正在以错误的顺序执行步骤吗?

现在我有一个循环通过每个球到:

  • 模拟迭代
  • 检查与其他球的碰撞
  • 检查与场景边界的碰撞

我应该补充一点,我与界限有摩擦,当发生球与球的碰撞时,只是为了失去能量。

以下是处理冲突的部分代码:

    // Sim an iteration
    for (Ball ball : balls) {
        ball.gravity.set(gravity.x, gravity.y);

        if (ball.active) {
            ball.sim();

            // Collide against other balls
            for (Ball otherBall : balls) {
                if (ball != otherBall) {
                    double dist = ball.pos.distance(otherBall.pos);
                    boolean isColliding = dist < ball.radius + otherBall.radius;
                    if (isColliding) {
                        // Offset so they aren't touching anymore
                        MVector dif = otherBall.pos.copy();
                        dif.sub(ball.pos);
                        dif.normalize();
                        double difValue = dist - (ball.radius + otherBall.radius);
                        dif.mult(difValue);
                        ball.pos.add(dif);

                    // Change this velocity
                    double mag = ball.vel.mag();
                    MVector newVel = ball.pos.copy();
                    newVel.sub(otherBall.pos);
                    newVel.normalize();
                    newVel.mult(mag * 0.9);
                    ball.vel = newVel;

                    // Change other velocity
                    double otherMag = otherBall.vel.mag();
                    MVector newOtherVel = otherBall.pos.copy();
                    newOtherVel.sub(ball.pos);
                    newOtherVel.normalize();
                    newOtherVel.mult(otherMag * 0.9);
                    otherBall.vel = newOtherVel;
                    }
                }
            }
        }
    }

4 个答案:

答案 0 :(得分:2)

如果这是检查球之间交互的唯一代码,那么问题似乎很清楚。在平衡状态下,球无法在另一个球上停留。

让我们说你有一个球直接在另一个上面。当您计算由于重力引起的顶球加速度时,您还应该像您发布的那样进行碰撞检查,除非这次检查dist <= ball.radius + otherBall.radius。如果是这种情况,那么你应该假设球之间的法向力等于重力,并且将重力分量与连接两个球的中心的矢量一致。如果你没有做到这一点,那么顶部球会加速进入底部,触发你发布的碰撞代码,你就会感到紧张。

当球与场景绑定接触时,必须使用类似的逻辑。

答案 1 :(得分:1)

由于我一直在尝试自己的Phys2D引擎(只是为了好玩),我知道你在谈论。 (以防万一 - 你可以在这里查看我的演示:http://gwt-dynamic-host.appspot.com/ - 在那里选择“Circle Collisions Demo”,并在此处输入相应的代码:https://github.com/domax/gwt-dynamic-plugins/tree/master/gwt-dynamic-main/gwt-dynamic-module-bar)。

问题在于迭代的本质和碰撞后果的无限循环。例如,球到达了场景角落,它经历了至少3个力的向量:从墙壁反弹的冲动,从地板反弹的冲动和重力的冲动 - 在你总结所有3个冲动之后,根据失去的能量算法减少它,你有让你的球应该是新的矢量。但是,例如这种冲动将它引导到墙上 - 然后你必须根据所有的东西重新计算一组矢量:弹跳,冲动,重力等的能量。即使万一所有这些冲动都很小,你永远不会得到它们全部0 ,因为双精度和公差比较常数的精确度 - 因为你有“抖动”和“滑动”效果。

实际上,大多数现有的2D引擎都有这样或那样的效果:你可以在这里看到它们:http://brm.io/matter-js/demo/#wreckingBall或者这里:http://box2d-js.sourceforge.net/index2.html - 它们实际上只是让小的冲动更快被吸收当整个系统变得或多或少稳定时停止迭代,但并不总是可能。

无论如何,我只是建议不要重新发明自己的轮子,除非它只是为了你的乐趣 - 或者为了更好地理解这些东西。

对于最后一个(JFF) - 这是一个很好的教程:http://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331

对于实际情况,我建议使用现有的引擎,例如: Unity(https://unity3d.com/learn/tutorials/modules/beginner/2d/physics2d)或Box2d(http://box2d.org/

希望这有帮助。

答案 2 :(得分:1)

迭代所有球并改变每次迭代的球位置可能是导致不稳定的原因,你向左移动球以避免在右侧发生碰撞,然后你将球推入左侧的另一个球,并且然后左球试图再次将它推回去。

从头顶我可以建议在做任何关于定位之前总结每个球上的所有力量。如果你从球上迭代#34;在顶部&#34; (离重力源/方向最远)你可能会达到稳定的状态。

基本上,顶球需要首先计算自身与其下方的球之间的力,加上重力,然后球下方会知道顶球有多大的力,并且还会加重力增加它将球推到它下面的力。当所有球都知道他们用力推动的力量时,你可以将力量转化为运动。

答案 3 :(得分:1)

你模拟球的物理特性必然会导致不稳定。您的碰撞分辨率会尝试通过碰撞深度向相反方向投射其中一个来分离球。这可以固定这两个球的重叠,但是(特别是当球被堆叠时)机会现在与另一个球重叠。

有很多方法可以解决渗透问题。最简单的方法之一是添加&#34;偏差&#34;或者对两个物体施加一点推力迫使它们在接下来的几帧中分离。这允许能量传播并迫使所有物体分开。问题是,偏见经常会高估并导致一些反弹。为了解决这个问题,我建议你阅读顺序冲动。

让物理看起来很逼真并不像看起来那么容易。除非你不介意不稳定,否则我建议花一些时间阅读不同的技术或使用Box2D之类的引擎。