当我的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;
        }
    

    最佳答案

    很难读取其他人的代码,但是我认为这是一种可能的方法(完全是集思广益),尽管我当然无法对其进行测试:

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

  • 顺便说一句,当您的玩家跳跃时撞到屋顶时,当前代码会发生什么?

    关于c# - AABB碰撞造成的平台跳跃问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6416725/

    10-10 18:39