【问题标题】:Platform jumping problems with AABB collisionsAABB 碰撞导致的平台跳跃问题
【发布时间】:2011-06-20 19:58:30
【问题描述】:

当我的 AABB 物理引擎解析交叉点时,它会通过找到穿透较小的轴,然后“推出”该轴上的实体来实现。

考虑“向左跳”的例子:

  • 如果velocityX 大于velocityY,AABB 将实体在Y 轴上推出,有效地停止跳跃(结果:玩家停在半空中)。
  • 如果velocityX 小于velocitY(图中未显示),程序将按预期运行,因为AABB 在X 轴上将实体推出。

我该如何解决这个问题?

源码:

public void Update()
    {
        Position += Velocity;
        Velocity += World.Gravity;

        List<SSSPBody> toCheck = World.SpatialHash.GetNearbyItems(this);

        for (int i = 0; i < toCheck.Count; i++)
        {
            SSSPBody body = toCheck[i];
            body.Test.Color = Color.White;

            if (body != this && body.Static)
            {                   
                float left = (body.CornerMin.X - CornerMax.X);
                float right = (body.CornerMax.X - CornerMin.X);
                float top = (body.CornerMin.Y - CornerMax.Y);
                float bottom = (body.CornerMax.Y - CornerMin.Y);

                if (SSSPUtils.AABBIsOverlapping(this, body))
                {
                    body.Test.Color = Color.Yellow;

                    Vector2 overlapVector = SSSPUtils.AABBGetOverlapVector(left, right, top, bottom);

                    Position += overlapVector;
                }

                if (SSSPUtils.AABBIsCollidingTop(this, body))
                {                      
                    if ((Position.X >= body.CornerMin.X && Position.X <= body.CornerMax.X) &&
                        (Position.Y + Height/2f == body.Position.Y - body.Height/2f))
                    {
                        body.Test.Color = Color.Red;
                        Velocity = new Vector2(Velocity.X, 0);

                    }
                }
            }               
        }
    }

    public static bool AABBIsOverlapping(SSSPBody mBody1, SSSPBody mBody2)
    {
        if(mBody1.CornerMax.X <= mBody2.CornerMin.X || mBody1.CornerMin.X >= mBody2.CornerMax.X)
            return false;
        if (mBody1.CornerMax.Y <= mBody2.CornerMin.Y || mBody1.CornerMin.Y >= mBody2.CornerMax.Y)
            return false;

        return true;
    }
    public static bool AABBIsColliding(SSSPBody mBody1, SSSPBody mBody2)
    {
        if (mBody1.CornerMax.X < mBody2.CornerMin.X || mBody1.CornerMin.X > mBody2.CornerMax.X)
            return false;
        if (mBody1.CornerMax.Y < mBody2.CornerMin.Y || mBody1.CornerMin.Y > mBody2.CornerMax.Y)
            return false;

        return true;
    }
    public static bool AABBIsCollidingTop(SSSPBody mBody1, SSSPBody mBody2)
    {
        if (mBody1.CornerMax.X < mBody2.CornerMin.X || mBody1.CornerMin.X > mBody2.CornerMax.X)
            return false;
        if (mBody1.CornerMax.Y < mBody2.CornerMin.Y || mBody1.CornerMin.Y > mBody2.CornerMax.Y)
            return false;

        if(mBody1.CornerMax.Y == mBody2.CornerMin.Y)
            return true;

        return false;
    }
    public static Vector2 AABBGetOverlapVector(float mLeft, float mRight, float mTop, float mBottom)
    {
        Vector2 result = new Vector2(0, 0);

        if ((mLeft > 0 || mRight < 0) || (mTop > 0 || mBottom < 0))
            return result;

        if (Math.Abs(mLeft) < mRight)
            result.X = mLeft;
        else
            result.X = mRight;

        if (Math.Abs(mTop) < mBottom)
            result.Y = mTop;
        else
            result.Y = mBottom;

        if (Math.Abs(result.X) < Math.Abs(result.Y))
            result.Y = 0;
        else
            result.X = 0;

        return result;
    }

【问题讨论】:

  • 您应该考虑在 www.gamedev.stackexchange.com 上发布此内容。也就是说,我现在正在深入研究代码,看看能否帮助您。

标签: c# collision-detection physics aabb


【解决方案1】:

很难阅读其他人的代码,但我认为这是一种可能(纯粹是头脑风暴)的解决方法,尽管我当然无法对其进行测试:

  1. 在发生碰撞检测之前,将玩家速度保存到某个临时变量。
  2. 完成碰撞响应后,检查玩家的 X 或 Y 位置是否已更正
  3. 如果 X 位置已更改,请手动将玩家的 Y 速度重置(作为一种“安全重置”)到响应前的速度。

顺便问一下,当你的玩家在跳跃时撞到屋顶时,你当前的代码会发生什么?

【讨论】:

  • 改变速度不会解决任何问题,因为速度不受碰撞响应的影响。响应只是改变玩家的位置,保持速度不变。当玩家撞到屋顶时,它会漂浮一段时间然后又落下来。这是有意的,因为当它到达天花板时我没有将速度设置为 0。
【解决方案2】:

我也有同样的问题。甚至 Microsoft 平台游戏 starterskit 似乎也有这个错误。

到目前为止,我发现的解决方案是使用多重采样 (argh) 或使用对象的移动方向:仅移动这两个对象之间的距离,当检测到碰撞时不再移动(并对每个轴执行此操作) .

【讨论】:

    【解决方案3】:

    我发现的一个可能的解决方案是在根据玩家的速度解析之前对对象进行排序。

    【讨论】:

      猜你喜欢
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多