OnCollision播放器与任何对象发生碰撞

时间:2014-02-27 02:05:36

标签: c# xna

我正在使用farseer物理引擎创建2D平台游戏,我正在努力弄清楚如何使用OnCollision,即使我看到this,我仍然试图掌握这个概念。这就是我的工作with。我想知道玩家什么时候打地面,所以我可以得到一个名为isJumping的bo​​ol。当玩家跳跃时,isJumping是真的,这样玩家就不会继续跳跃。 (我也希望有一个地面布尔可以说,“在地上干草”。)

这段代码的问题是我会得到一个空引用。我也只是检测地板物体,我是否需要检测一下我放在屏幕上的其他物品以及地板物体?

public bool OnCollision(Fixture fixtureA, Fixture fixtureB,  FarseerPhysics.Dynamics.Contacts.Contact contact)
    {
        if (contact.IsTouching())
        {
            if (fixtureA.Body.GetType() == Person.GetType() & fixtureB.Body.GetType() == game1.floor.GetType())
            {
                ground = true;
                isJumping = false;
            }
        }
        return false;
    }
  1. 我要对这段代码做的是先找出玩家是否正在接触地面,不是击中它的头部或撞击物体的左壁或右壁。 (也是为了检查玩家是否可以跳跃)

  2. 如果我在游戏中添加更多对象,我将不得不为此功能添加更多代码,即使我只想检测玩家的底部是否与对象发生碰撞,让玩家停止?

  3. 我应该能够检测到玩家是否与其顶部或侧面发生碰撞,是否正确?

1 个答案:

答案 0 :(得分:0)

确定玩家是否在空中的更好方法是使用Ray Casting。

例如,我使用这样的方法来确定光线碰撞的对象(注意:RayCastResult只是一个保存结果的类):

    public static RayCastResult FindClosest(this World world, Vector2 startPoint, Vector2 endPoint, Func<Fixture, bool> filter)
    {
        var result = new RayCastResult ();

        world.RayCast((f, p, n, fr) =>
        {
            if (filter(f)) {
                return -1.0f;
            }

            result.Fixture = f;
            result.HitPoint = p;
            result.HitPointSurfaceNormal = n;
            return fr;
        }, startPoint, endPoint);

        return result;
    }

根据您在RayCast回调函数中返回的内容,您可以使用Ray Casting执行以下操作:

  1. 在你的回调夹具中返回-1然后将忽略夹具并且光线将继续(对于忽略某些对象很有用,如上所示)
  2. 返回0光线将终止(这将返回遇到的第一个灯具,但可能不是最近的物体,因为碰撞引擎不一定按此顺序处理碰撞)
  3. 返回分数然后光线将在此时停止(这是上面用来最终找到最近的对象)
  4. 返回1然后光线将继续直到它结束(您可以使用它来获取光线碰撞的所有灯具的列表)
  5. Farseer Ray Casting引擎基于Box2D的引擎,非常好documented over here

    然后可以通过这种方式使用上述方法来确定物体是否在空中(由于无法获得100%的准确度,因此需要一些魔法数字)。在我的情况下,我从一个圆的中心投射一条光线,然后检查光线投射是否遇到了圆圈附近的任何物体:

        private bool RunInAirHitTest(Vector2 start, Vector2 end)
        {
            var hitTest = _world.FindClosest (start, end, f => IsHit(f.Body));
            var hitDistance = (hitTest.HitPoint - start).Length ();
            return !hitTest.HitOccurred || hitDistance > _wheelRadius * 1.2f;
        }