XNA控制相机/模型的旋转

时间:2018-09-27 21:36:28

标签: c# rotation controls xna monogame

在我开始之前:我尝试过gamedev.stackexchange,但是没有人回答,所以我认为我会在这里测试自己的运气:)

我是3D编程的新手,我正在尝试制作一款游戏,让玩家可以控制迷宫周围的角色。

我当前的问题不是真的使鼠标居中并读取它来旋转相机-尽管我希望将来,现在WASD运动也可以旋转,我想这意味着我需要旋转轴。我已经尝试了大约1-2个小时,环顾四周,有人说要使用四元数,而有人说要使用矩阵,但是到目前为止,我还没法做任何事情。为了澄清,当我按住W时,它会向前移动。但是,如果我然后旋转相机向右看并按住W,它将向相机的左侧移动<---如果可能,我想解决这个问题

我对如何做或如何做非常困惑,我会提供我的Camera类和Game1类,尽管我会警告您-我不太擅长将事情布置得很好。我不是一个经验丰富的程序员,所以要我将知识应用到我的项目中可能要花我一段时间才能做好,谢谢:D

    public class Camera
{
    float angle = 1f;
    float currentAngle;
    public Vector3 cameraPosition;
    public Vector3 cameraTarget;
    public Matrix worldMatrix { get; set; }
    public Matrix viewMatrix { get; set; }
    public Matrix projectionMatrix { get; set; }
    public Matrix rotationMatrix;
    Matrix playerPos;
    Matrix movement;
    Vector3 position;

    public void SetMovement(Matrix inMovement)
    {
        movement = inMovement;
    }

    public void SetPosition(Vector3 inPosition)
    {
        position = inPosition;
    }

    public Camera(GraphicsDevice graphics, Vector3 inTarget)
    {
        rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(0f));
        cameraTarget = new Vector3(0f, 0f, 0f);
        cameraPosition = new Vector3(0f, -1f, 3.5f);
        playerPos = Matrix.CreateScale(0.01f) *
                    Matrix.CreateTranslation(position);
        projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f),
                                                    graphics.DisplayMode.AspectRatio,
                                                    0.03f, 100f);
        worldMatrix = Matrix.CreateWorld(inTarget, Vector3.Forward, Vector3.Up);

        viewMatrix = Matrix.CreateLookAt(position, inTarget, Vector3.Up);
    }

    public virtual void Update()
    {
        if(Keyboard.GetState().IsKeyDown(Keys.Right))
        {
            currentAngle += angle;
            rotationMatrix = Matrix.CreateRotationY(MathHelper.ToRadians(currentAngle)) * rotationMatrix;
            currentAngle = 0;
        }
        if (Keyboard.GetState().IsKeyDown(Keys.Left))
        {
            currentAngle += angle * -1;
            rotationMatrix = rotationMatrix * Matrix.CreateRotationY(MathHelper.ToRadians(currentAngle));
            currentAngle = 0;
        }
        viewMatrix = Matrix.CreateLookAt(new Vector3(cameraPosition.X + position.X, cameraPosition.Y + position.Y + 1.02f,   //FIRST PERSON CAMERA
            position.Z + 0.013f), cameraTarget + position + new Vector3(0f,1f,0f), Vector3.Up) * rotationMatrix;             
        //viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);                                        //MAP VIEW CAMERA

    }

}

这是Game1

    public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Model map, player;
    Camera playerCamera;
    Vector3 playerPosition;
    Matrix playerCurrentPosition, cameraCurrentPosition;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferHeight = 1080;
        graphics.PreferredBackBufferWidth = 1920;
    }

    protected override void Initialize()
    {
        player = Content.Load<Model>("ball2");
        playerPosition = new Vector3(-0.84f, 0.86f, 0.02f);
        playerCamera = new Camera(GraphicsDevice, new Vector3(0f, 0f, 0f));
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        map = Content.Load<Model>("newMap");


    }

    protected override void UnloadContent()
    {
    }

    protected override void Update(GameTime gameTime)
    {
        playerCamera.SetMovement(playerCurrentPosition);
        playerCamera.SetPosition(playerPosition);
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();
        if (Keyboard.GetState().IsKeyDown(Keys.W))
            playerPosition.Y += 0.01f;
        if (Keyboard.GetState().IsKeyDown(Keys.A))
            playerPosition.X -= 0.003f;
        if (Keyboard.GetState().IsKeyDown(Keys.S))
            playerPosition.Y -= 0.003f;
        if (Keyboard.GetState().IsKeyDown(Keys.D))
            playerPosition.X += 0.003f;
        playerCurrentPosition =
            Matrix.CreateScale(0.01f) *
            Matrix.CreateTranslation(playerPosition);
        cameraCurrentPosition = Matrix.CreateTranslation(playerPosition - new Vector3(0f, 0.1f, 0f));
        playerCamera.Update();

        base.Update(gameTime);
    }

    public void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
    {
        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.View = view;
                effect.Projection = projection;
                effect.World = world;
                effect.EnableDefaultLighting();
            }
            mesh.Draw();
        }
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Crimson);

        DrawModel(map, playerCamera.worldMatrix, playerCamera.viewMatrix, playerCamera.projectionMatrix);
        DrawModel(player, playerCamera.worldMatrix * playerCurrentPosition, playerCamera.viewMatrix, playerCamera.projectionMatrix);

        base.Draw(gameTime);
    }
}

1 个答案:

答案 0 :(得分:0)

显然有不同的方法,所以这可能不是最优雅的方法:

让我们假设您将相机旋转角度存储为角度rotationY(您将需要第二角度,但这可能不会影响步行方向)。

我假设您当前有一些这样的代码:

if (kbState.IsKeyDown(Keys.W))
    position += new Vector3(1, 0, 0) * elapsedTime;

我们现在要做的是旋转方向矢量,其旋转量与旋转相机的旋转量相同。我们可以为此使用矩阵变换(用sin和cos编写旋转会更快,但是由于每帧只运行一次,因此不必担心):

Matrix rotation = Matrix.CreateRotationY(rotationY);
Vector3 forward = Vector3.Transform(new Vector3(1, 0, 0), rotation);
if (kbState.IsKeyDown(Keys.W))
    position += forward * elapsedTime;

基本上就是这样。对于向后运动,请使用-forward;对于横向运动,请使用相同的矩阵旋转第二个矢量。

执行此操作的方法有多种:您可以从相机的角度计算向前和向后的矢量(我认为从视图矩阵中获取它们非常快)。这可能会更快,但是再一次,这里的性能应该没什么太大的。