2
\$\begingroup\$

I am having some weird issues with my camera. I am trying to make it so it is a first person camera, that when the user presses the W or Up key, it moves towards where the camera is looking. My issue is i can either have it working like that, but no collision working, I did a little debugging and the players world wasn't aligned with the camera even after changing them manually to be such. Or the other method, has collision but the camera doesn't go to where its facing, but just along the X and Z axis.

here is my camera class (The previewMove is meant to check for bounding spheres? I just dont know how i'd do that really):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Game7
{
    class Camera : GameComponent
    {
        public Vector3 cameraPosition;
        private Vector3 cameraRotation;
        private float cameraSpeed;
        private Vector3 cameraLookAt;

        private Vector3 mouseRotationBuffer;
        private MouseState currentMouseState;
        private MouseState previousMouseState;



        // Properties

        public Vector3 Position
        {
            get { return cameraPosition; }
            set
            {
                cameraPosition = value;
                UpdateLookAt();
            }
        }

        public Vector3 Rotation
        {
            get { return cameraRotation; }
            set
            {
                cameraRotation = value;
                UpdateLookAt();
            }
        }

        public Matrix Projection
        {
            get;
            protected set;
        }

        public Matrix View
        {

            get
            {
                return Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up);
            }
        }

        //Constructor 
        public Camera(Game game, Vector3 position, Vector3 rotation, float speed)
            : base(game)
        {
            cameraSpeed = speed;

            // projection matrix
            Projection = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.PiOver4, 
                Game.GraphicsDevice.Viewport.AspectRatio,
                0.05f, 
                1000.0f);

            // set camera positiona nd rotation
            MoveTo(position, rotation);

            previousMouseState = Mouse.GetState();
        }

        // set Camera's position and rotation
        private void MoveTo(Vector3 pos, Vector3 rot)
        {
            Position = pos;
            Rotation = rot;
        }

        //update the look at vector
        private void UpdateLookAt()
        {
            // build rotation matrix
            Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y);
            // Look at ofset, change of look at
            Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
            // update our cameras look at vector
            cameraLookAt = cameraPosition + lookAtOffset;
        }

        // Simulated movement
        public Vector3 PreviewMove(Vector3 amount)
        {
                // Create rotate matrix
                Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);
                // Create a movement vector
                Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
                movement = Vector3.Transform(movement, rotate);

                return cameraPosition + movement;
        }

        // Actually move the camera
        private void Move(Vector3 scale)
        {
            MoveTo(PreviewMove(scale), Rotation);
        }

        // updat method
        public override void Update(GameTime gameTime)
        {
            // smooth mouse?
            float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

            currentMouseState = Mouse.GetState();

            KeyboardState ks = Keyboard.GetState();

            // input

            Vector3 moveVector = Vector3.Zero;

            if (ks.IsKeyDown(Keys.W))
                moveVector.Z = 1;
            if (ks.IsKeyDown(Keys.S))
                moveVector.Z = -1;
            if (ks.IsKeyDown(Keys.A))
                moveVector.X = 1;
            if (ks.IsKeyDown(Keys.D))
                moveVector.X = -1;

            if (moveVector != Vector3.Zero)
            {
                //normalize it
                //so that we dont move faster diagonally
                moveVector.Normalize();
                // now smooth and speed
                moveVector *= dt * cameraSpeed;
                // move camera
                Move(moveVector);
            }

            // Handle mouse input

            float deltaX;
            float deltaY;

            if(currentMouseState != previousMouseState)
            {
                //Cache mouse location
                deltaX = currentMouseState.X - (Game.GraphicsDevice.Viewport.Width / 2);
                deltaY = currentMouseState.Y - (Game.GraphicsDevice.Viewport.Height / 2);

                // smooth mouse ? rotation
                mouseRotationBuffer.X -= 0.01f * deltaX * dt;
                mouseRotationBuffer.Y -= 0.01f * deltaY * dt;

                if (mouseRotationBuffer.Y < MathHelper.ToRadians(-75.0f))
                    mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(-75.0f));
                if (mouseRotationBuffer.Y > MathHelper.ToRadians(75.0f))
                    mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(75.0f));

                Rotation = new Vector3(-MathHelper.Clamp(mouseRotationBuffer.Y, MathHelper.ToRadians(-75.0f), MathHelper.ToRadians(75.0f)), MathHelper.WrapAngle(mouseRotationBuffer.X), 0);

                deltaX = 0;
                deltaY = 0;

            }

            // Alt + F4 to close now.
            // Makes sure the mouse doesn't wander across the screen (might be a little buggy by showing the mouse)
            Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);

            previousMouseState = currentMouseState;

                base.Update(gameTime);
        }


    }
}

And here is how i am building the camera and controlling it in my game1.cs:

camera = new Camera(this, new Vector3(player_x, player_y, player_z), Vector3.Zero, 5f);
            Components.Add(camera);

if (kb.IsKeyDown(Keys.Up))
                {
                    player_z = player_z + 0.05f;
                    world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
                    // use this code for any standard collision
                    if ((IsCollision(ball, world_player, ball, world_cannon)) || (IsCollision(ball, world_player, ball, walls[0])) || (IsCollision(ball, world_player, ball, walls[1])) || (IsCollision(ball, world_player, ball, walls[2])) || (IsCollision(ball, world_player, ball, walls[3])) || (IsCollision(ball, world_player, ball, walls[4])) || (IsCollision(ball, world_player, ball, walls[5])))
                    {
                        player_z = player_z - 0.05f;
                        //camera.Position = new Vector3(player_x, player_y, player_z);
                        world_player = Matrix.CreateTranslation(player_x, player_y, player_z);
                    }
                }
                if (kb.IsKeyDown(Keys.Down))
                {
                    player_z = player_z - 0.05f;
                    world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
                    // use this code for any standard collision
                    if ((IsCollision(ball, world_player, ball, world_cannon)) || (IsCollision(ball, world_player, ball, walls[0])) || (IsCollision(ball, world_player, ball, walls[1])) || (IsCollision(ball, world_player, ball, walls[2])) || (IsCollision(ball, world_player, ball, walls[3])) || (IsCollision(ball, world_player, ball, walls[4])) || (IsCollision(ball, world_player, ball, walls[5])))
                    {
                        player_z = player_z + 0.05f;
                        world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
                    }
                }

                // this makes it first person with collision but bad movement
                //camera.Position = new Vector3(player_x, player_y, player_z);

                // this makes it a better first person movement but no collision. 
                //world_player = Matrix.CreateTranslation(camera.Position);

Thank you for any help, i really am at a loss currently with this.

\$\endgroup\$
-1
\$\begingroup\$

XNA has a Vector3.Forward, transform that with your cameras viewmatrix and if necessary set your y component to zero and normalize.

Generally if this gives you trouble you should refresh your basic understanding of linear algebra.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.