【问题标题】:How to calculate bounce angle?如何计算弹跳角度?
【发布时间】:2010-10-09 01:18:56
【问题描述】:

我玩了一段时间,但我就是想不通。

我做了一个可以发射导弹的坦克,当导弹击中墙壁时,我希望它们反弹,但我希望它们反弹到正确的角度。

现在我没有任何障碍物,导弹只是在我制造的viewportRectangle之外弹开。

我正在寻找的解决方案是否相当先进?

有没有相对简单的方法?

【问题讨论】:

  • 这是一个问题,如果你去打台球,这个问题的解决方案可能会立即变得显而易见。

标签: c# xna physics


【解决方案1】:

对于完美粒子(和光),反射角等于入射角,如下图所示(来自 commons.wikimedia.org)。

Wikipedia page on reflection 非常擅长解释其工作原理。

如果考虑到物体的弹性和材料以及障碍物,情况会稍微复杂一些,但这对于大多数应用程序来说可能已经足够了。

【讨论】:

    【解决方案2】:

    a = 2w - b

    其中:
    a => 结果角度
    w => 墙壁或地板或天花板角度
    b => 球角度

    这是我在尝试找到最简单的公式来计算球在墙壁、天花板和地板上反弹的角度后得出的结论。结果可能超出 +360 或 -360 度,但它们仍然是等效角度。

    例如,如果天花板角度为 270 度,球角度为 30 度,则结果角度为 510 度,相当于 +150 度或 -210 度。如果天花板使用 90 度而不是 270 度,结果仍然是 150 度。

    【讨论】:

      【解决方案3】:
      if(!Collide(Missle, Mainchar)){
      (Velocity.x)*-1;
      (Velocity.y)*-1;
      }
      

      它很有效,很简单,祝你好运。

      【讨论】:

      • 是的,没有。这使对象沿其原始向量反向返回。那不是镜面反射。
      【解决方案4】:

      我遇到过这个问题,我发现的唯一方法就是分离碰撞轴!

      试试看:

      x += velocity * Math.cos(angle * Math.PI /180);
      y += velocity * Math.sin(angle * Math.PI /180);
      
      if (x < 0 || x > canvas.width) {
           angle = 180 - angle;   
      }
      else if (y < 0 ||y > canvas.height) {
           angle = 360 - angle; 
      }
      

      希望对你有帮助!

      【讨论】:

      • 不是理想的通用解决方案,但这正是我现在需要的(从画布边缘反射)。出于某种原因,我无法让我的大脑自行得出这个解决方案。
      【解决方案5】:

      您可能会认为,由于您的墙壁与坐标轴对齐,因此编写特殊情况代码是有意义的(对于垂直墙壁,否定速度的 x 坐标;对于水平墙壁,否定 y 坐标的速度)。然而,一旦你让游戏在垂直和水平墙壁上运行良好,你可能会想到的下一个问题是,“任意角度的墙壁怎么样?”所以从一开始就值得考虑一般情况。

      在一般情况下,假设您的导弹速度为 v,并以表面法线 n 击中墙壁。

      v分割成垂直于墙壁的u和平行于墙壁的w分量。

      地点:

      u = (v · n / n · n) n
      w = v - u

      这里,v · n 是向量 vndot product。有关如何计算它的说明,请参阅链接。点积 n · n 求值为法向量长度的平方;如果您始终以unit vectors 的形式保留法线,则 n · n = 1,您可以省略除法。

      弹起后,平行于壁的运动分量受摩擦影响f,垂直于壁的分量受弹性影响,可以以@987654323的形式给出@r.

      所以碰撞后的速度是v′ = f w - r u。在完全弹性、无摩擦的碰撞中,v′ = w - u;也就是说,运动反映在碰撞点的法线附近,如比尔回答中给出的图表所示。

      这种方法在三个维度上也同样有效。

      (显然这是一个非常简化的弹跳概念;它没有考虑角动量或变形。但对于许多类型的视频游戏来说,这种简化是完全足够的。)

      【讨论】:

      • 我同意从垂直和水平墙壁的特殊情况编码开始是错误的方法。这不是通往正确路线的垫脚石,而是一条死路。
      • 大家好,这是一个很棒的解释,但我认为它有一个错误。不应该是 u = -n ( v.n / n.n ) 吗?毕竟,你的方向与n相反。
      • 只有我一个人对 v.n 的用法感到困惑,而不是使用 v·n 吗?当我阅读 n.n 时,我的大脑简直爆炸了;认为正常有一个元素称为正常。 (我习惯 C++ 太多了?)。
      • 计算表面法线 n 见这个问题:stackoverflow.com/questions/1243614/…
      • 非常感谢,这很完美。如果其他人想知道,您可以使用 ux = (dotproduct(v,n)) * nuywxwy
      【解决方案6】:

      我认为更简单的方法是使用导弹的速度而不是计算角度。假设你有一个导弹,它有xVelocityyVelocity 来表示它的水平和垂直运动。这些速度可以是正数或负数,以表示左、右、上或下。

      • 如果导弹击中顶部或底部边界,则反转 yVelocity 的符号。
      • 如果导弹击中左边界或右边界,则反转 xVelocity 的符号。

      这将使相反轴的运动保持不变。

      借用ChrisF's answer的图片,假设导弹从位置I开始。

      xVelocityyVelocity 都为正值(在 2D 图形中,右下方通常为正值),导弹将沿指示的方向行进。让我们分配值

      xVelocity = 3
      yVelocity = 4
      

      当导弹在位置C击中墙壁时,它的xVelocity 不应该改变,但它的yVelocity 应该被反转为-4,以便它朝上方向返回,但一直向右。

      这种方法的好处是您只需要跟踪导弹的xPositionyPositionxVelocityyVelocity。仅使用这四个组件和游戏的更新率,导弹总是会在正确的位置重新绘制。一旦遇到更复杂的障碍物(不是直角或移动),使用 X 和 Y 速度比使用角度要容易得多。

      【讨论】:

      • 我用导弹的角度让它前进。使用 Math.Sin 和 Math.Cos。我在理解另一种方式时遇到了问题,使用速度,就像 XNA 示例中的炮弹一样。所以我只需要改变导弹的角度,它就会自行前进。
      • 这只有在你所有的墙都与坐标轴对齐的情况下才有效,即使这样你也需要垂直和水平墙的单独案例。在一般情况下,可能更容易正确处理。
      • 不,不是。在一般情况下,您需要做的是使用一些三角函数来对齐矢量,以便墙为了您的计算而变为水平或垂直,然后进行此计算,并将其转换回来。它只是多 2-4 次三角计算,但并不容易。
      • @Karl:不需要三角函数!
      • 当然,您可以轻松调整它以适用于静止或移动的不同角度的对象。只需使用碰撞中两个物体的速度来计算每个物体的新速度。
      【解决方案7】:

      除了您所问的具体物理问题之外,我推荐 Wendy Stahler 的《游戏程序员的数学和物理入门》一书。我发现它对我的游戏/物理编程项目非常有用。

      本书随附的代码是 C++,但如果您了解 C#,则很容易进行转换。

      祝你好运!

      【讨论】:

        【解决方案8】:

        这确实是一个物理问题,所以如果你不是物理学家(既然你问这个问题,我会认为你不是)它需要大量阅读和头脑风暴才能得到它正确的。

        我建议阅读this 维基百科条目以了解有关您问题深度的基本概念。

        如果你只是想让它“看起来合理”,那么我不会太担心它并使用 Bill the Lizard 的答案,但是如果你想让它正确,你将拥有相当一次冒险。不要让这吓到你!祝你好运!

        【讨论】:

        • 除非他在写物理模拟引擎,否则这与物理无关。 OP 只想要简单的镜面反射。
        【解决方案9】:

        180-a 并非在所有情况下都有效,除非您只是在 X 增加时在顶面上进行反弹。

        一个方向是 XNA 论坛或获取 XNA 示例代码。它是 C#,用于构建游戏。我并不是说你想在 XNA 中构建你的游戏,但它是一个很棒的工具,而且它是免费的。

        【讨论】:

        • 我正在使用 XNA。是的,有一个问题..在窗口的左右边界发射导弹时,导弹可以正常反射,但是在窗口的底部或顶部边界射击时,我可以看到反射,而不是右侧角度。
        【解决方案10】:

        一点也不复杂——伪代码:

        angleObjectHitWall = a;
        bounceAngle = 180-a;
        

        当然,这是一个非常简单的计算,一旦你开始考虑材料、重力、不直的墙壁等因素,就完全无关紧要了......

        【讨论】:

        • 错误号。这仅适用于入射角和反射角相同的情况。
        • @bergin - 对于游戏中的理想化粒子来说,几乎总是如此。
        猜你喜欢
        • 1970-01-01
        • 2021-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多