0

I have come to a position with my 3D game where I am now trying to perfect the camera. What I ultimately want is a working first person camera that stops when it collides with a wall. I assume you do this by having the camera move with a model and have the model collide to stop the camera also, i am just having issues seeing how to do that.

I have the model working so it stops, i just need to lock the camera from moving also. So far this is the code I have, making the model stop with collison:

 if (player_health != 0)
            {
                if (kb.IsKeyDown(Keys.Left))
                {
                    player_x = player_x + 0.05f;
                    world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
                    if (IsCollision(ball, world_player, ball, world_spike))
                    {
                        player_x = player_x - 0.05f;
                        world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
                        player_health = 0;
                    }
                    if (IsCollision(ball, world_player, ball, world_bullet[0]))
                    {
                        player_health = 0;
                    }
                    // 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])))
                    {
                        player_x = player_x - 0.05f;
                        world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
                    }
                }

My camera added into the game1 class:

camera = new Camera(this, new Vector3(10f, 3f, 5f), Vector3.Zero, 5f);
            Components.Add(camera);

And the camera class itself (I have been told this is rather over complicated? for a camera class, but the simpler ones didnt work):

namespace Game7
{
    class Camera : GameComponent
    {
        private 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
        private 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);
        }


    }
}

The Preview Move part of the camera class is meant to be where it detects for collision, at least the guide i followed said so, i just dont see how to integrate it. Thanks for any help or input, even if it is just a link to another guide or resource, would be very appreciated!

jayelj
  • 47
  • 6

1 Answers1

0

If your hero model (player) already has move functionality and collision functionality, and you want the camera to follow the model, then you can simplify the camera update tremendously.

Assuming after moving the player, the new position and/or orientation of the player is represented in player_world, simply borrow the location and orientation information stored in the player_world matrix to build a view matrix each frame.

//after moving player and setting its matrix accordingly:
view = Matrix.Invert(player_world);

And that is your complete camera class update. This creates a view matrix that is in the same position as the player and facing the same direction he is. If the player model stops because it hits a wall, then the camera (view matrix) stops too, because it is built from the player's 'stopped' matrix. No need to create a whole class for moving and rotating the camera around when the movement and rotation is the same as the player.

Sometimes the local player model origin would be located at the player's feet or belly and you want the camera up in the head where the eyes are. If so, simply apply something like this:

//after moving player and setting its matrix accordingly:
Matrix camera_world = player_world;
camera_world *= Matrix.CreateTranslation(Vector3.Up * ??f);// set ??f to the height difference between feet and head
view = Matrix.Invert(camera_world);
Steve H
  • 5,479
  • 4
  • 20
  • 26
  • Is the view = Matrix.Invert(player_world); code supposed to go in the camera or game class? the view matrix in the game class isn't used, i should have taken it out infact. the view matrix i am using is camera.view. I figured out a way to make the camera move and stop with the player by adding the camera = new camera code into the update, however that made it so i couldn't move the mouse either. – jayelj Jan 23 '16 at 15:47
  • It can go in either one, as long as you don't do anything else with the view matrix after this line and it can be accessed by all 3d draw calls. – Steve H Jan 24 '16 at 01:57
  • Hey! my players matrix is as follows: private Matrix world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z)); I don't have an orientation for it? not yet anyways. Another thing is I can't inherit my player_world because the camera class seems to break when I try to use it, by adding a new Game1 game to be able to use its properties. – jayelj Jan 26 '16 at 23:59
  • sounds like you might need more help than a reply here. My email address is in my profile, send me an email and I'll reply with an answer. – Steve H Jan 27 '16 at 13:20