Getting started with XNA – First Person Camera

來源:互聯網
上載者:User
Getting started with XNA - First Person Camera

What’s a game or an interactive presentation without a way to move around? So in this tutorial, I’ll show you how to make a first person camera. As usual, this tutorial will work on the code of the previous one, available for download here.

 

Let’s start with some basic concepts: yaw, pitch and roll. Yaw is when you move your head from right to left or left to right. Pitch is when you move your head up and down, and roll is when you roll your head from one shoulder to another. The illustration below shall shed some more light.

前後左右旋轉。

 

Two other concepts you need to comprehend are view and projection. The view establishes the orientation of the camera: its position, where it’s looking, and its orientation.

兩個重要的概:view + projection. view指的是觀察者的方位,往什麼地方看,以及方向。

 

The projection establishes how the camera projects its view onto the screen: the field of view, the aspect ratio of the viewport, and the boundaries (in distance) of what the camera can see: the near plane and the far plane.

投影包括了:field of view, aspect ratio of viewport, boundaries

 

Ok, let’s start coding. Open up your project and add a class called Camera. Make sure it inherits from DrawableGameComponent.
public class Camera : DrawableGameComponent

First, we’re going to add a static variable, so we have easy access to the active camera. Most games don’t have just one camera, they have a first person camera, third person camera, … Note that there are better ways to do this, using a factory class and interfaces, but for this tutorial, it will do just fine.
private static Camera activeCamera = null;

Then add a variable for our view and projection, who represent (as explained above) the orientation of the camera and the way it’s projected to the screen.
// View and projection
private Matrix projection = Matrix.Identity;
private Matrix view = Matrix.Identity;

Then we’ll add some variables we’ll use to calculate our view and projection: the position of the camera, the angle of the camera, the speed of movement and the turn speed.
//
private Vector3 position = new Vector3(0, 0, 1000);
private Vector3 angle = new Vector3();
private float speed = 250f;
private float turnSpeed = 90f;

Next we’ll add some properties, so we can access some of these variables externally.
public static Camera ActiveCamera
{
get { return activeCamera; }
set { activeCamera = value; }
}

public Matrix Projection
{
get { return projection; }
}

public Matrix View
{
get { return view; }
}

public Vector3 Position
{
get { return position; }
set { position = value; }
}

public Vector3 Angle
{
get { return angle; }
set { angle = value; }
}

Also, in the constructor, we’ll check if there is an active camera. If not, we’ll set the active camera to this camera.
public Camera(Game game) : base(game)
{
if (ActiveCamera == null)
ActiveCamera = this;
}

When you’re in a game, you can keep turning around if u want, there is no limit to the amount of rotation. In order to achieve this, we need to keep our mouse cursor in the center of the screen. We’ll start by doing this in the Initialize method. Then we’ll calculate the movement and reset the mouse to the center of the screen each time the update method is called.
public override void Initialize()
{
int centerX = Game.Window.ClientBounds.Width / 2;
int centerY = Game.Window.ClientBounds.Height / 2;
//
Mouse.SetPosition(centerX, centerY);
//
base.Initialize();
}

Ok, we’ve set the basis. Only two more methods to implement. In the LoadGraphicsContent method we’ll calculate our projection. In the Update method, we’ll calculate our view. First the projection:
protected override void LoadGraphicsContent(bool loadAllContent)
{
float ratio = (float)GraphicsDevice.Viewport.Width / (float)GraphicsDevice.Viewport.Height;
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, ratio, 10, 10000);
//
base.LoadGraphicsContent(loadAllContent);
}

The projection will be a perspective field of view, with a near plane of 10 and a far plane of 10000. Below a graphic illustration.

(No pic)

 

We’re almost there. Now to calculate our view. Start by adding the update method.
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}

First, we’ll put the time that has gone past since the previous update in a variable called delta.
float delta = (float)gameTime.ElapsedGameTime.TotalSeconds;

And then we’ll capture the current state of the mouse and keyboard, so we’ll know which keys were pressed and where the mouse has moved to.
KeyboardState keyboard = Keyboard.GetState();
MouseState mouse = Mouse.GetState();

Now we have the current state, let’s just set the mouse cursor back in the center of the screen, so we don’t forget it later on.
int centerX = Game.Window.ClientBounds.Width / 2;
int centerY = Game.Window.ClientBounds.Height / 2;

Mouse.SetPosition(centerX, centerY);

Let’s adjust our angle variable according to the mouse movement.
angle.X += MathHelper.ToRadians((mouse.Y - centerY) * turnSpeed * 0.01f); // pitch
angle.Y += MathHelper.ToRadians((mouse.X - centerX) * turnSpeed * 0.01f); // yaw

Now that we have our angle, we can easily calculate our pitch and yaw vector (relative movement). I have to warn you, you’ll need your basic trigonometry, if you’re a bit rusty, fresh it up ;-). We’ll need this so we can move in the direction we’re looking at.
Vector3 forward = Vector3.Normalize(new Vector3((float)Math.Sin(-angle.Y), (float)Math.Sin(angle.X), (float)Math.Cos(-angle.Y)));
Vector3 left = Vector3.Normalize(new Vector3((float)Math.Cos(angle.Y), 0f, (float)Math.Sin(angle.Y)));

Ok, so let’s update our position according to the keys pressed.
if (keyboard.IsKeyDown(Keys.Up))
position -= forward * speed * delta;

if (keyboard.IsKeyDown(Keys.Down))
position += forward * speed * delta;

if (keyboard.IsKeyDown(Keys.Right))
position -= left * speed * delta;

if (keyboard.IsKeyDown(Keys.Left))
position += left * speed * delta;

if (keyboard.IsKeyDown(Keys.PageUp))
position += Vector3.Down * speed * delta;

if (keyboard.IsKeyDown(Keys.PageDown))
position += Vector3.Up * speed * delta;

So, that’s it, we have all we need to calculate our view. We’ll translate to our position and multiply that by our rotations, just that simple.
view = Matrix.Identity;
view *= Matrix.CreateTranslation(-position);
view *= Matrix.CreateRotationZ(angle.Z);
view *= Matrix.CreateRotationY(angle.Y);
view *= Matrix.CreateRotationX(angle.X);

There, that’s it, our camera class is finished. All we need to do now is add a camera to the components of our game class and tell our forklift to use the view and the projection of our camera. So put this in the Initialize method of our Game1 class.
this.Components.Add(new Camera(this));

Finally, update the view and projection in the draw code of our forklift.
effect.View = Camera.ActiveCamera.View;
effect.Projection = Camera.ActiveCamera.Projection;

So, when you press F5 know, you’ll be able to move and look around. You can download the full source of this tutorial of course.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.