Subscribe

RSS Feed (xml)

Powered By

Powered by Blogger

Google
 
xnahelp.blogspot.com

Jumat, 04 April 2008

Creating a First Person Camera

We can build on our stationary camera by adding a first person camera. The main thing
we want to do is to add in a way to move back and forth and to each side. Before we
start, we should create a new camera class and inherit from the one we have. We can call
this new class FirstPersonCamera. The following is the Update method for this new class:
public override void Update(GameTime gameTime)
{
// TODO: Add your update code here
//reset movement vector
movement = Vector3.Zero;
if (input.KeyboardState.IsKeyDown(Keys.A) ||
(input.GamePads[0].ThumbSticks.Left.X < 0))
{
movement.X—;
Creating a First Person Camera 103
3
LISTING 5.1 Continued
}
if (input.KeyboardState.IsKeyDown(Keys.D) ||
(input.GamePads[0].ThumbSticks.Left.X > 0))
{
movement.X++;
}
if (input.KeyboardState.IsKeyDown(Keys.S) ||
(input.GamePads[0].ThumbSticks.Left.Y < 0))
{
movement.Z++;
}
if (input.KeyboardState.IsKeyDown(Keys.W) ||
(input.GamePads[0].ThumbSticks.Left.Y > 0))
{
movement.Z—;
}
//make sure we don’t increase speed if pushing up and over (diagonal)
if (movement.LengthSquared() != 0)
movement.Normalize();
base.Update(gameTime);
}
The conditional logic should look familiar. It is identical to our stationary camera, except
we changed where we were reading the input and what values it updated. We are reading
the A, S, W, D keys and the left thumb stick. We are not looking at the mouse for movement.
The value we are setting is a movement vector. We are only setting the X (left and
right) and Z (back and forth) values. At the end of the conditions we are normalizing our
vector as long as the length squared of the vector is not zero. This makes sure that we are
not allowing faster movement just because the user is moving diagonally. There is no
more code in the FirstPersonCamera object. The rest of the changes were made back on
our original camera object.
We declared the movement as a protected member field of type Vector3 called movement
inside of our original Camera object. We also declared a constant value for our movement
speed. Both of these are listed here:
protected Vector3 movement = Vector3.Zero;
private const float moveRate = 120.0f;
We also set the access modifier of our input field to protected so our FirstPersonCamera
could access it:
protected IInputHandler input;
104 CHAPTER 5 Input Devices and Cameras
Finally we updated the last part of our Update method to take the movement into
account when transforming our camera:
//update movement (none for this base class)
movement *= (moveRate * timeDelta);
Matrix rotationMatrix;
Vector3 transformedReference;
Matrix.CreateRotationY(MathHelper.ToRadians(cameraYaw), out rotationMatrix);
if (movement != Vector3.Zero)
{
Vector3.Transform(ref movement, ref rotationMatrix, out movement);
cameraPosition += movement;
}
//add in pitch to the rotation
rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(cameraPitch)) *
rotationMatrix;
// Create a vector pointing the direction the camera is facing.
Vector3.Transform(ref cameraReference, ref rotationMatrix,
out transformedReference);
// Calculate the position the camera is looking at.
Vector3.Add(ref cameraPosition, ref transformedReference, out cameraTarget);
Matrix.CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector,
out view);
Besides just moving our local variables closer together, the only things that changed are
the items in bold type. We take our movement vector and apply our move rate to it
(taking into account our time delta, of course). The second portion is the key. We transformed
our movement vector by our rotation matrix. This keeps us from just looking in a
direction but continuing to move straight ahead. By transforming our movement vector
by our rotation matrix we actually move in the direction we are looking! Well, the movement
actually happens in the next statement when we add this movement vector to our
current camera position. We wrapped all of this in a condition to see if any movement
happened because we do not want to take a performance hit to do the math if we did not
move.
Another thing to note is that because we were creating a first person camera we only
transformed our movement vector by the yaw portion of our rotation matrix. We did
not include the pitch, as that would have allowed us to “fly.” If we did want to create a
flying camera instead, we could simply move this following statement before the code
that is bold:
105
5
//add in pitch to the rotation
rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(cameraPitch)) *
rotationMatrix;

0 komentar: