似乎无法获得平滑的3D碰撞XNA

时间:2016-12-13 11:18:27

标签: c# visual-studio-2015 3d xna collision-detection

我正在制作3D游戏。播放器是“相机”。我希望它不要穿过已实现的墙壁。但是现在我希望它能够像任何其他fps那样沿着墙“滑行”。这是代码:并提前感谢:

protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();
        float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

        keyState = Keyboard.GetState();

        camera.Update(gameTime);

        if (keyState.IsKeyDown(Keys.W)) camera.moveVector.Z = 1;
        if (keyState.IsKeyDown(Keys.S)) camera.moveVector.Z = -1;
        if (keyState.IsKeyDown(Keys.A)) camera.moveVector.X = 1;
        if (keyState.IsKeyDown(Keys.D)) camera.moveVector.X = -1;
        if (keyState.IsKeyDown(Keys.Space)&&camera.Position.Y>=0.5f) camera.moveVector.Y = 0.5f;

        if (camera.moveVector != Vector3.Zero)
        {
            //We don't want to make the player move faster when it is going diagonally.
            camera.moveVector.Normalize();
            //Now we add the smoothing factor and speed factor
            camera.moveVector *= (dt * camera.cameraSpeed);


            Vector3 newPosition = camera.PreviewMove(camera.moveVector);

            bool moveTrue = true;


            if (newPosition.X < 0 || newPosition.X > Map.mazeWidth) moveTrue = false;
            if (newPosition.Z < 0 || newPosition.Z > Map.mazeHeight) moveTrue = false;
            foreach (BoundingBox boxes in map.GetBoundsForCell((int)newPosition.X, (int)newPosition.Z))
            {
                if (boxes.Contains(newPosition) == ContainmentType.Contains)
                {
                    moveTrue = false;
                }
            }

            if (moveTrue) camera.Move(camera.moveVector);


            base.Update(gameTime);

以下是推动运动的代码:

        //Updating the look at vector
        public void UpdateLookAt()
        {
            //Built a rotation matrix to rotate the direction we are looking
            Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y);

        // Build a look at offset vector 
        Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);

        //Update our camera's look at the vector
        cameraLookAt = (cameraPosition + lookAtOffset);

    }


    //Method to create movement and to check if it can move:)
    public Vector3 PreviewMove(Vector3 amount)
    {
        //Create a rotation matrix to move the camera
        Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);

        //Create the vector for movement
        Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
        movement = Vector3.Transform(movement, rotate);

        // Give the value of the camera position +ze movement
        return (cameraPosition+movement);
    }

    //Method that moves the camera when it hasnt'collided with anything
    public void Move(Vector3 scale)
    {
        //Moveto the location
        MoveTo(PreviewMove(scale), Rotation);
    }

已经考虑过使用xna给出的反转方法。但我似乎无法找到正常的。我试图将相机平行移动到墙上。但我无法做到这一点。任何帮助都是有用的。

1 个答案:

答案 0 :(得分:0)

如果您发现某个点与边界框相交,则必须检查入口点所在的六个面中的哪一个。这可以按如下方式完成:在旧相机位置和新相机位置之间构建一个线段:

p = (1 - t) * oldPos + t * newPos

,您只使用oldPosnewPos的维度,这对于脸部很有趣(例如,对于左/右脸,采用x坐标)。 p是面部的相应坐标。计算每个面的t并找到t最大的面,忽略该点已经落后的面(即面法线的点积和从面到点的方向是负)。这将是您的切入点所在的面孔。您需要做的就是调整相关坐标(左/右脸的x坐标等),使其不在边界内(例如右侧面设置为newPos.x = boundingBox.MaxX)。这等于将点投影到边界框表面上,等效于仅使用与框平行的运动矢量分量(如果发生交叉)。

顺便说一下,上述公式的解决方案是:

t = (p - oldPos) / (newPos - oldPos)