XNA Game Engine Tutorial Series #7 – First Person Camera

Note: Finish Chapter 6.5 before starting this chapter if you started the tutorial series before 12/10/2008

This one is quick because I’ve been very busy leading up to christmas, so here goes. This tutorial is on building a first person camera, the type used in most games these days. It can be moved and rotated. Later on we’ll learn how to apply physics to the camera so it can interact with the environment.

using Microsoft.Xna.Framework;
using System;

namespace Innovation
{
    // A simple first person camera. Accepts rotation and translation
    public class FPSCamera : Camera
    {
        // Keeps track of the rotation and translation that have been
        // added via RotateTranslate()
        Vector3 rotation;
        Vector3 translation;

        public FPSCamera(GameScreen Parent) : base(Parent) { }
        public FPSCamera() : base() { }

        // This adds to rotation and translation to change the camera view
        public void RotateTranslate(Vector3 Rotation, Vector3 Translation)
        {
            translation += Translation;
            rotation += Rotation;
        }

        public override void Update()
        {
            // Update the rotation matrix using the rotation vector
            Rotation = MathUtil.Vector3ToMatrix(rotation);

            // Update the position in the direction of rotation
            translation = Vector3.Transform(translation, Rotation);
            Position += translation;

            // Reset translation
            translation = Vector3.Zero;

            // Calculate the new target
            Target = Vector3.Add(Position, Rotation.Forward);

            // Have the base Camera update all the matrices, etc.
            base.Update();
        }
    }
}

Here’s how it would be used in a game. You will need to do a few things first though. First make sure the camera you are making is of type FPSCamera in the LoadContent() method. Then do the following:

KeyboardDevice keyboard = Engine.Services.GetService<KeyboardDevice>();
MouseDevice mouse = Engine.Services.GetService<MouseDevice>();
FPSCamera cam = (FPSCamera)Engine.Services.GetService<Camera>();

Vector3 inputModifier = new Vector3(
    (keyboard.IsKeyDown(Keys.A) ? -1 : 0) + (keyboard.IsKeyDown(Keys.D) ? 1 : 0),
    (keyboard.IsKeyDown(Keys.Q) ? -1 : 0) + (keyboard.IsKeyDown(Keys.E) ? 1 : 0),
    (keyboard.IsKeyDown(Keys.W) ? -1 : 0) + (keyboard.IsKeyDown(Keys.S) ? 1 : 0)
);

cam.RotateTranslate(new Vector3(mouse.Delta.Y * -.002f, mouse.Delta.X * -.002f, 0), inputModifier * .05f);

if (mouse.WasButtonPressed(MouseButtons.Left))
{
    PhysicsActor act = new PhysicsActor(
        Engine.Content.Load<Model>("Content/ig_box"),
        new BoxObject(new Vector3(.5f), cam.Position, Vector3.Zero));

    act.Scale = new Vector3(.5f);
    act.PhysicsObject.Mass = 1000;

    Vector3 dir = cam.Target - cam.Position;
    dir.Normalize();

    act.PhysicsObject.Velocity = dir * 10;
}

And that’s all there is to it! Press the mouse button and you should shoot a box away from the camera!

Download the Code for this Chapter
Back to Game Engine Tutorial Series

19 Responses to “XNA Game Engine Tutorial Series #7 – First Person Camera” »

  1. Comment by holy — December 7, 2008 @ 8:52 pm

    I have a question. MathUtil has no Vector3ToMatrix method.
    I can’t find it.

  2. Comment by holy — December 7, 2008 @ 9:01 pm

    and rotation is not matrix. I think this means RotationMatrix.

  3. Comment by Sean James — December 11, 2008 @ 4:58 pm

    Read 6.5 below

  4. Comment by Eibach — December 18, 2008 @ 3:03 pm

    is there a reason you dont use Quaternions for rotation?

  5. Comment by Sean — December 18, 2008 @ 4:13 pm

    1. We don’t have to calculate the matrices using Matrix.CreateFromYawPitchRoll each frame to draw each object, we just use the matrix we already have.

    2. JigLibX uses matrices, so by using them we can save conversions when interfacing with it.

  6. Comment by Eibach — December 21, 2008 @ 8:18 pm

    Ah ha. Well that makes sense I guess. Just thinking about doing a simulation game like a flying game or somthing =P

  7. Comment by Chris — February 1, 2009 @ 3:15 pm

    It seems that on the xbox 360, the collision is somewhat broken. I run this on it and about 3/4 of the boxes that i shoot are just flying right through everything. I wonder if its an issue with the JigLibX library on the 360. Any ideas why this is?

  8. Comment by Chris — February 1, 2009 @ 3:20 pm

    Hmm, looks like its something to do with the size of the object. If i scale the box to 2.0f then it runs fun. Weird.

  9. Comment by Jose — March 3, 2009 @ 9:35 pm

    I tried running the program, but I couldn’t leave it, not even with Task Manager (mainly because the mouse pointer wouldn’t move). I had to force my laptop off in order to quit it (a real pain).

    My point is, shouldn’t you make a command for quitting the program with the press of a button (like Esc or something)? Just asking.

  10. Comment by Sean — March 3, 2009 @ 9:38 pm

    Alt + F4

  11. Comment by Jose — March 3, 2009 @ 9:54 pm

    Didn’t know that.

    Thanks!

  12. Comment by Freeman — March 6, 2009 @ 2:49 pm

    How do you add dynamic light affects and water affects?

  13. Comment by ISAF — June 25, 2009 @ 12:25 am

    got my implementation working smoothly. Altho for me drawing boxes is 1 behind. I see 8 instead of 9 at the start. when I fire, it puts the 9th box, and some invisible one knocks it over.

    Not sure where that goes wrong. (Had this before adding inputhandling)

    When I fire now, it puts a box at the previous target and then fires another invisible one.

    Any clue where to fix this?

    Next stop for me: build in inverted boolean and expand the rotatetranslate method to support that (Y axis).

    (small note: invert the x rotation)

    If people want I could supply the piece of code

  14. Comment by Hellboytb — June 30, 2009 @ 1:46 am

    Is there a way for me to instead of using a FPS Camera, create a camera class thats also for 3rd person and activate it via a key pressed… Eg: click once for on and once for off.

  15. Comment by required — July 13, 2009 @ 12:55 pm

    Does someone know how to attach the camera to the physic-boxes? Ive tried it but the camera just flew out into space… where no camera has been before…
    I made a var to store it and setthe cams pos with to the pos of the box.

  16. Comment by Steven — October 22, 2009 @ 3:33 pm

    Hi,

    Very nice tutorials. I don’t understand the math in your camera classes, can you please give me an explanation? In the Camera class for example there is a statement saying “rotationMatrixCopy.Forward = newForward;”

    Why do you assign a vector to a matrix? This does not make sense to me for i’m not very well at home in vector math…can you maybe give a site where i can find these things? I tried to google it but all i get is very basic linear algebra stuff and nothing that can explain what is going on here.

    Thanks,

    Steven

  17. Comment by spider — October 4, 2010 @ 8:15 pm

    lol funny ur code dont even load what a doosh bag

  18. Comment by Dustin — December 12, 2010 @ 1:34 pm

    //Exit
    if (Engine.Services.GetService().WasKeyPressed(Keys.Escape))
    Exit();

  19. Comment by Dustin — December 12, 2010 @ 1:36 pm

    Nothing wrong with the code, but you need to start at Tutorial #1 and work forward. Given the date of your post I’m assuming you’re using XNA 4.0 which will require several code changes because of breaking changes in the framework, as well as an updated JigLibx.

RSS feed for comments on this post. TrackBack URI

Leave a comment