概念检查器:Farseer中的碰撞情况

时间:2012-11-15 08:40:40

标签: c# xna farseer

我现在已经使用Farseer了很长一段时间,从事物理教学平台项目。关于我大脑中的发动机有一些问题很长一段时间没有得到解决,其中很多都与发动机的碰撞处理有关。

许多人似乎在理解引擎的工作方面存在问题,部分原因是因为Farseer缺少适当的API。对于那些知道确认以下概念而 KILL 任何错误的概念,这可能是一个好主意。

概念0:两个阶段

Farseer中的碰撞分为两个阶段:

  1. 广角相撞
  2. 精确碰撞(请更正我使用的术语,如果还有其他更正式的名称......)
  3. 概念1:Broadphase

    使用广泛相位碰撞的Farseer将在场景中发现潜在的碰撞。所述宽相碰撞试验由......完成。

    1. 使用四叉树,可在包装中找到" Farseer.Collision"。
    2. 班级" Farseer.Dynamics.World"引用了" Farseer.Collision.QuadTreeBroadphase"。
    3. " Farseer.Collision.QuadTreeBroadphase"引用了" Farseer.Collision.QuadTree"。
    4. 还进行了进一步的边界框测试。
    5. 如果我们发现需要知道哪一对灯具有可能发生碰撞,我们可能会这样做......

      /* Game.Initialize */
      public override void Initialize() {
          OtherIrrelevantInitCode();
          _world.OnBroadphaseCollision += BroadphaseHandler;
          base.Initialize();
      }
      public void BroadphaseHandler(ref FixtureProxy fp1, ref FixtureProxy fp2) {
          // code to read about fp1 and fp2
      }
      
    6. 但是......

      小问题1

      有哪些常见情况对我们了解哪些灯具可能会发生碰撞有用?

      概念2:事件的含义

      两个关键字的定义:

      1. 触摸:两个物体接触。数组Manifold.Points 非空
      2. 碰撞:两个物体第一次相互接触
      3. BeforeCollision 表示两个对象不碰撞不接触

        OnCollision 表示两个对象碰撞,但触摸不会触发此事件。

        AfterCollision 表示两个对象发生碰撞,但现在仅触及

        OnSeparation 表示两个对象,但现在不是。

        概念3:使用事件

        广泛的碰撞测试和精确的碰撞测试始终

        可以通过在事件 OnCollision 中返回false或使用IgnoreCollision方法来禁用精确碰撞。

        我听过不止一次人们说"只是让OnCollision空了并且返回真实"。究竟是什么意思?使用这些事件意味着我们希望在上述事件发生时应用其他效果(例如杀死敌人,得分,播放声音等)。

1 个答案:

答案 0 :(得分:3)

此答案适用于Farseer Physics 3.3.1 (当前稳定版本,撰写时)


广泛阶段只是一种性能优化。它可以快速确定可以碰撞的内容,以便无法碰撞的东西不会有更昂贵的窄相位碰撞检测运行。


根据我的经验,Farseer中的事件的设计并不尽如人意。我发现我必须为自己的游戏修改它们 - 但幸运的是,这段代码实际上并不难以阅读和修改。此外,文档在一些地方也不准确。

以下是Farseer Physics 实际中的事件:

BeforeCollision 在广泛阶段注册新的潜在冲突时,在为两个灯具创建Contact对象之前发生。您可以通过在事件处理程序中返回Contact来阻止false的创建。

Contact的存在并不一定意味着两个灯具实际接触 - 只是宽广的阶段成功了。 Contact可以触摸/不触摸,可以启用/禁用它们(它们开始启用且不触摸)。

OnCollision从不接触变为触摸时,会发生

Contact 。您可以通过返回false来禁用联系人。奇怪的是,如果你返回true,你可以重新启用另一个事件处理程序在该步骤上禁用的联系人(这是我为自己的游戏改变的事情之一)。

只有启用的触摸式触点才会对物理模拟产生任何影响。

OnSeparation OnCollision相反:当联系人从触摸变为不触摸时触发。这里没有办法禁用/启用联系人。

对于该帧上的物理模拟中涉及的每个AfterCollision都会调用

Contact (所以:那些已启用,触摸,而不是在一个睡着的岛屿中)。它是在物理模拟步骤之后调用的,但在清理之前 - 最明显的是在清除Body.ForceBody.Torque之前(方便声音效果等)。


通常你只是使用这些事件来触发你的效果 - 粒子,声音,游戏机制,比如摧毁物体等等。在这种情况下,您订阅任何您想要的,做您喜欢的任何事情,然后返回true(不禁用/覆盖联系人)。

如果你想搞乱物理引擎或禁用联系人(特别是当你不小心重新启用它们时,使用另一个事件处理程序,如前面提到的那样)会变得更加复杂。如果Farseer的内置事件对您不起作用,那么进入其代码并添加自己的代码是完全合理的。在这个先进的水平上,从源代码构建实际上是必要的,这样你就可以确切地检查究竟发生了什么。