How To: Make a First-Person Camera

Demonstrates how to create a first-person camera.

The example controls the camera by using the method shown in How To: Rotate and Move a Camera, with an additional offset for the camera to place it where the game avatar's head should be. The example assumes a model has been added to the project as described in How To: Render a Model.

This technique is implemented in the FuelCell game, a game developed by following a series of focused articles that discuss basic 3D game development. For more information, see FuelCell: Setting the Scene.

The Complete Sample

The code in the topic shows you the technique. You can download a complete code sample for this topic, including full source code and any additional supporting files required by the sample.

Making a First-Person Camera

To make a first-person camera

  1. Precalculate the camera's offset from the avatar.

    The offset is used to place the camera roughly at the location of the avatar's head.

    Vector3 avatarHeadOffset = new Vector3(0, 10, 0);
  2. Track the position and rotation of the avatar during gameplay.

  3. Create a rotation Matrix using CreateRotationY and the avatar's current direction.

    Matrix rotationMatrix = Matrix.CreateRotationY(avatarYaw);
  4. Use the rotation Matrix and Vector3.Transform to transform a copy of the camera's head offset.

    // Transform the head offset so the camera is positioned properly relative to the avatar.
    Vector3 headOffset = Vector3.Transform(avatarHeadOffset, rotationMatrix);
  5. Calculate the current position of the camera.

    The position of the camera will be the position of the avatar, plus the avatar's transformed head offset.

    // Calculate the camera's current position.
    Vector3 cameraPosition = avatarPosition + headOffset;
  6. Use the rotation Matrix and Vector3.Transform to transform a copy of the camera's reference vector.

    // Create a vector pointing the direction the camera is facing.
    Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix);
  7. Calculate the position at which the camera is looking.

    This "look-at" position will be the camera's position, plus the camera's transformed reference vector.

    // Calculate the position the camera is looking at.
    Vector3 cameraLookat = transformedReference + cameraPosition;
  8. Create a new view Matrix.

    You can create the new Matrix by passing the camera position and camera look-at to CreateLookAt. The view Matrix controls how world coordinate values are transformed to camera coordinates.

    view = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f));
  9. Use CreatePerspectiveFieldOfView to create a new projection Matrix.

    The projection Matrix controls how camera coordinate values are transformed to screen coordinates.

    Viewport viewport = graphics.GraphicsDevice.Viewport;
    float aspectRatio = (float)viewport.Width / (float)viewport.Height;
    proj = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip);
  10. Loop through each model in the world drawing it as described in How To: Render a Model using the projection matrix and view matrix created above.

    For the world matrix, use Matrix.CreateTranslation and the object's current position in the world.

    void DrawBoxes()
        for (int z = 0; z < 9; z++)
            for (int x = 0; x < 9; x++)
                DrawModel(box, Matrix.CreateTranslation(x * 60, 0, z * 60), boxTexture);
    /// <summary>
    /// Draws the 3D specified model.
    /// </summary>
    /// <param name="model">The 3D model being drawn.</param>
    /// <param name="world">Transformation matrix for world coords.</param>
    /// <param name="texture">Texture used for the drawn 3D model.</param>
    void DrawModel(Model model, Matrix world, Texture2D texture)
        foreach (ModelMesh mesh in model.Meshes)
            foreach (BasicEffect be in mesh.Effects)
                be.Projection = proj;
                be.View = view;
                be.World = world;
                be.Texture = texture;
                be.TextureEnabled = true;

Community Additions