【问题标题】:2d Elastic Collision with Circles带圆圈的 2d 弹性碰撞
【发布时间】:2021-07-02 22:48:22
【问题描述】:

我已经看到有很多关于此的帖子,但我找不到与我想做的事情相关的帖子, 我使用了这里的公式: https://www.vobarian.com/collisions/2dcollisions2.pdf 还有这个: https://www.plasmaphysics.org.uk/programs/coll2d_cpp.htm 我认为它们的区域基本相同,现在我的问题是我的一个圆圈始终是静态的,而我想要的是当另一个圆圈直接击中它时,我希望它以相同的速度反弹,但是这些公式有圆圈静止不动,大概是因为它会将能量传递给另一个圆圈,然后另一个圆圈会移开。 我尝试做类似bounce = vel.x pre collision - vel.y post collision 并将其添加或减去到 vel.x 后碰撞,它有点工作但不是真的,角度是错误的,取决于球的方向从它可能会向上而不是向下反弹,向左而不是向右, 可能需要很多 if/else 语句才能开始工作。 有人可以提出一些建议吗? 这是函数的代码:

void Collision2(sf::CircleShape* b1, sf::CircleShape* b2, sf::Vector2f vel1,sf::Vector2f& vel2) {
        //vel1 is 0,0  but i might want to use it later
        //mass
        float m1 = 10;
        float m2 = 10;
        //normal vector
        sf::Vector2f nVec((b2->getPosition().x - b1->getPosition().x), (b2->getPosition().y - b1->getPosition().y));
        //unit vector
        sf::Vector2f uNVec(nVec / sqrt((nVec.x * nVec.x) + (nVec.y * nVec.y)));
        //unit tangent vec
        sf::Vector2f uTVec(-uNVec.y, uNVec.x);

        float v1n = (uNVec.x * vel1.x) + (uNVec.y * vel1.y);
        float v2n = (uNVec.x * vel2.x) + (uNVec.y * vel2.y);
        float v1t = uTVec.x * vel1.x + uTVec.y * vel2.y;
        float v2t = (uTVec.x * vel2.x) + (uTVec.y * vel2.y);


        //v1t and v1n after collision
        float v1tN = v1t;
        float v2tN = v2t;
        float v1nN = (v1n * (m1 - m2) + (2 * m2) * v2n) / (m1 + m2);
        float v2nN = (v2n * (m2 - m1) + (2 * m1) * v1n) / (m1 + m2);

        //new velocities
        sf::Vector2f vel1N(v1nN*uNVec);
        sf::Vector2f vel1tN(v1tN * uTVec);
        sf::Vector2f vel2N(v2nN * uNVec);
        sf::Vector2f vel2tN(v2tN * uTVec);
        vel1 = (vel1N + vel1tN);
        vel2 = (vel2N + vel2tN);

    }

【问题讨论】:

  • 您写道“我的一个圈子总是静态”。你的意思是恒定的吗?我没有看到函数const 的任何参数。有助于更快地理解。
  • 碰撞只是动量守恒问题。完美的弹性碰撞不会由于任一物体的变形而损失能量。在圆之间的碰撞中,施加给每个物体的力是在碰撞点施加的法向力。切线简单地定义了碰撞力垂直作用的平面。为确保能够提供准确的答案,请提供A Minimal, Complete, and Verifiable Example (MCVE)
  • 静态我的意思是一个圆圈是固定的,当另一个圆圈击中它时不会移动,所以我想要说一个弹球击中一个圆形保险杠并弹回。在发布这个问题之后,我又摆弄了一下,并注意到如果我改变移动到 0 的圆的质量并将固定圆的质量保持在 10 我得到了我想要的效果,我不知道那会怎样但是,当我为 2 个移动圆圈添加碰撞时会影响事物。
  • 在这种情况下,您知道碰撞后的反弹速度为零。这将允许您利用动量和能量向后工作,以修复另一个圆的碰撞后幅度和方向。

标签: c++ sfml collision


【解决方案1】:

物理部分

您添加的资源很好地说明了它背后的物理原理。当两个球碰撞时,它们在它们之间传递动量。在弹性碰撞中,这种转移使系统的能量保持不变。

我们可以从惯性和动量的角度来考虑碰撞,而不是从速度开始。一个物体的动能一般是p^2/(2m),所以如果我们从运动的物体上传递dp,那么我们就会有能量的变化:dE = -pdp/m + dp^2/(2m) + dp^2/(2M) = 0。这里m 是移动的,M 是静止的质量。重新排列给出pdp/m = dp^2*(1/(2m) + 1/(2M))。我们可以考虑m = M 产生p = dp(即所有时刻都被转移(注意:这是一个简单的视图,只处理正面碰撞))。然而,在静止物体很大的极限(M >> m)中,结果将是dp = 2p,只是反弹。

编程

您可以通过将M 设置为允许的最大浮点值来获得结果(如果我记得 IEEE 标准中的1/inf == NaN,那么不幸的是它不起作用)。或者,您可以通过创建自定义类来在圆内进行碰撞:

class Circle : public sf::CircleShape{
    public:
        virtual collide (Circle*);
}

class StaticCircle : public Circle{
    public:
        collide (Circle*) override;
}

在第二个中,您可以省略除以圆的质量的任何项,因为它本质上是无限的。

【讨论】:

    猜你喜欢
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2021-09-26
    • 2014-02-27
    • 1970-01-01
    相关资源
    最近更新 更多