-1


我一直在尝试在 XNA 4.0 中开发一款 3d 前锋游戏(如 Temple Run)。
我碰到了一堵砖墙,所以任何帮助将不胜感激!
目前,我正在使用自己的碰撞检测方法,这需要将每个模型的尺寸硬编码到碰撞方法中。我尝试使用 Microsoft 的代码,直接在下面,但它总是返回 false:

  static bool CheckForCollisions(Entity c1, Entity c2)
    {
        for (int i = 0; i < c1.body.Meshes.Count; i++)
        {
            // Check whether the bounding boxes of the two cubes intersect.
            BoundingSphere c1BoundingSphere = c1.body.Meshes[i].BoundingSphere;
            c1BoundingSphere.Center += c1.position;

            for (int j = 0; j < c2.body.Meshes.Count; j++)
            {
                BoundingSphere c2BoundingSphere = c2.body.Meshes[j].BoundingSphere;
                c2BoundingSphere.Center += c2.position;

                if (c1BoundingSphere.Intersects(c2BoundingSphere))
                {
                    return true;
                }
            }
        }
        return false;
    }

这是从这里我的实体类中获取和修改的,如下所示。

我认为相关的我的代码是:

    public class Entity
    {
        public int rowID;
        public Model body;
        public Vector3 position;
        public float rotation = 0f;
        public float rotatePerFrame = 0f;
        protected internal float toRight = 0; 
        protected internal float toLeft = 0;
        protected internal float forward = 0;
        protected internal float back = 0;
        protected internal float bottom = 0;
        protected internal float top = 0;
        public void setDimensions(float right, float left, float front, float back, float top, float bottom)
        {
            this.toRight = right;
            this.toLeft = left;
            this.forward = front;
            this.back = back;
            this.top = top;
            this.bottom = bottom;
        }
        public Entity RotateEnt(Entity e,float degrees)//Psuedo-only accurate to 90 degrees.
        {
            float actual = MathHelper.ToDegrees(degrees);
            switch ((int)actual)
            {
                case 0:
                    break;
                case 90:
                  //  float temp = e.forward;
                  //  e.forward = e.toLeft;
                 //   e.toLeft =e.back ;
                 //   e.back = e.toRight;
                 //   e.toRight = temp;
                    float temp = e.forward;
                    e.forward = e.toRight;
                    e.toRight = e.back;
                    e.back = e.toLeft;
                       e.toLeft = temp;
                    break;
                case 180:
                    e.forward = e.back;
                    e.back = e.forward;
                    e.toRight = e.toLeft;
                    e.toLeft = e.toRight;
                    break;
                default: //case: 270

                    e.toRight = e.forward;
                    e.back = e.toRight;
                    e.toLeft = e.back;
                    e.forward = e.toLeft;
                    break;
            }


            return e;
        }
        public bool Collides(Entity e)
        {

            Entity c1 = RotateEnt(this, this.rotation);
            Entity c2 = RotateEnt(e, e.rotation);


            float myRightest = c1.position.X + c1.toRight;
            float myLeftest = c1.position.X - c1.toLeft;

             float hisRightest = c2.position.X + c2.toRight;
             float hisLeftest = c2.position.X - c2.toLeft;
            if(Collides1D(myLeftest, myRightest, hisLeftest, hisRightest))
            {

                float myTop = c1.position.Y + c1.top;
                float myBottom = c1.position.Y - c1.bottom;

                float hisTop = c2.position.Y + c2.top;
                float hisBottom = c2.position.Y - c2.bottom;
                if (Collides1D(myBottom, myTop, hisBottom, hisTop))
                {

                    float myBack = c1.position.Z - c1.forward;
                    float myForward = c1.position.Z + c1.back;

                    float hisBack = c2.position.Z - c2.forward;
                    float hisForward = c2.position.Z + c2.back;
                    if (Collides1D(myBack, myForward, hisBack, hisForward))
                    {

                        return true;
                    }
                }
            }
            return false;


        }
    }


    static bool Collides1D(float left1, float right1, float left2, float right2)
    {
        if (left1 >= left2 && left1 <= right2)
            return true;
        if (right1 >= left2 && right1 <= right2)
            return true;

        if (left2 >= left1 && left2 <= right1)
            return true;
        if (right2 >= left1 && right2 <= right1)
            return true;



        return false;
    }

在尝试旋转模型时,我自己的方法也搞砸了。
理想情况下,最好知道 Microsoft 的代码有什么问题,这样我就可以在任何地方使用它,而不必担心对象维度的硬编码。
如果有人能看到我自己的基本碰撞检测方法的快速修复,那也很棒。
我看过 Reimers 的教程,但目前我没有得到它们,也许我已经盯着自己的代码太久了......
你想要的任何其他信息,我可以尝试提供。如果这是问题,我也可以上传模型。我正在使用 Maya 的模型,导出为 FBX。我正在使用 MSVS 2010。非常感谢!
杰克

4

1 回答 1

0

我认为问题可能不在于冲突代码,而在于您如何更新实体的位置。我没有看到任何更新代码或 MoveForward() 等代码类型。不过,首先,我认为使用矩阵而不是一堆浮点值进行旋转会更容易。例如,您可以:

public class Entity
{
    ...
    public Matrix RotationMatrix = Matrix.Identity;
    public Vector3 position;

    Public Entity(Vector3 FaceDirection, Vector3 UpDirection, Vector3 Position)
    {
        ...
        position = Position
        RotationMatrix  = Matrix.CreateWorld(Position, FaceDirection, UpDirection)  
    }
}

那么如果你想旋转,你所要做的就是:

public Void RotateEnt(float Degrees)
{
    RotationMatrix *= Matrix.CreateFromAxisAngle(RotationMatrix.Up, MathHelper.ToRadians(Degrees));
}

如果你做了所有这些,那么你应该很容易能够更新你的实体的位置,我认为这是问题所在

public Void Update(GameTime gametime)
{
    position += RotationMatrix.Forward * gametime.ElapsedRealTime.TotalMilliseconds * x; //x = some number to scale up or down velocity.
}

如果你这样做,我认为你的实体的位置将被更新,然后应该解决你的碰撞问题。但是,不知道您如何更新实体的位置,我只是在猜测。高温高压

于 2013-08-09T01:09:42.127 回答