【问题标题】:XNA Controls Rotation in Addition to Camera/Model除了相机/模型外,XNA 还控制旋转
【发布时间】:2018-09-27 21:36:27
【问题描述】:

开始之前:我尝试了 gamedev.stackexchange,但没有人回复,所以我想我会在这里测试一下我的运气:)

我对 3D 编程比较陌生,我正在尝试制作一款玩家可以在迷宫中控制角色的游戏。

我目前的问题并不是真正让鼠标居中并读取它来旋转相机 - 虽然我希望将来这样做,但现在它正在让 WASD 运动也旋转,我认为这意味着我'd 需要旋转轴。我已经尝试了大约 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

    }

}

这是游戏 1

    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);
    }
}

【问题讨论】:

  • 这里有一个很好的提示:改用 Unity。
  • @Aybe 我愿意,但它是针对一个我们被标记为项目复杂性的项目。因此,XNA 总体上会给我带来更好的分数,因为实现功能比统一更复杂:)
  • 这是一个不太新的示例(未经测试):github.com/patteri/XNA-FPS,即使您不会使用 Unity,但这并不意味着您不能从中汲取灵感,例如 docs.unity3d.com/ScriptReference/Transform.html

标签: c# rotation controls xna monogame


【解决方案1】:

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

假设您将相机旋转存储为角度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,对于横向移动,使用相同的矩阵旋转第二个向量。

有不同的方法可以做到这一点:您可以从相机的角度计算前向和侧向向量(我认为从视图矩阵中获取它们非常快)。这可能会更快,但再次强调,性能在这里并不重要。

【讨论】:

    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    相关资源
    最近更新 更多