XNA контролирует вращение в дополнение к камере / модели - PullRequest
0 голосов
/ 28 сентября 2018

Перед тем, как начать: я попробовал gamedev.stackexchange, но никто не ответил, поэтому я решил проверить свою удачу здесь:)

Я относительно новичок в 3D-программировании и пытаюсь сделать игругде игрок может управлять персонажем вокруг лабиринта.

Моя текущая проблема не в том, чтобы заставить мышь быть в центре и читать ее, чтобы вращать камеру - хотя я бы хотел в будущем, прямо сейчасэто заставляет движение WASD также вращаться, я предполагаю, что это означает, что мне нужно повернуть ось.Я пытался около 1-2 часов смотреть по сторонам, некоторые говорят, что использовали Quaternions и другие матрицы, но я пока не смог заставить что-либо работать.Чтобы уточнить, когда я держу W, он движется вперед.Но если я поверну камеру, чтобы посмотреть вправо и удерживать W, она сместится влево от камеры <--- Я хочу исправить это, если это возможно </p>

Я очень потерян в том, что делатьили как лучше это сделать, я предоставлю свой класс 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);
    }
}

1 Ответ

0 голосов
/ 18 декабря 2018

Очевидно, что существуют разные подходы к этому, так что это может быть не самым элегантным:

Давайте предположим, что вы сохраняете поворот камеры как угол rotationY (вам понадобится второй угол, но этовероятно, не будет влиять на направление ходьбы).

Я предполагаю, что у вас сейчас есть такой код:

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

Теперь мы хотим повернуть вектор направления на ту же величинумы повернули камеру.Для этого мы можем использовать преобразования Matrix (запись вращения с использованием 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 и для движения в сторону, поверните второй вектор, используя ту же матрицу.

Есть разные способы сделать это: Вы можете вычислить вектор вперед и в сторону с точки зрения камеры (Я думаю, что это довольно быстро, чтобы получить их из матрицы просмотра).Возможно, это будет быстрее, но, опять же, производительность здесь не должна иметь большого значения.

...