A lot of people have asked me how to make certain types of camera, like third-person cameras or the kind that are used in a fighting game. In this article I will try to explain how to create these.
This is used in racing games (Need For Speed) and in "over-the-shoulder" games (like third-person shooter games). Let's explain how this is done.
First thing is to know the character's location and where it looking at. You can get this information from the model's LocalWorld matrix.
Vector3 position = new Vector3(localWorld.M41, localWorld.M42, localWorld.M43);
Vector3 lookAt = new Vector3(localWorld.M31, localWorld.M32, localWorld.M33);
With this we can calculate a point at the back of the model by subtracting the normalized lookAt vector from the position, and multiplying it by a value. To normalize a vector we can use the Vector3.Normalize method.
There is a faster way to do this. If we use the Vector3.TransformNormal method, we only need to set a vector with the offset that we want to apply to the position, and it will give us a new vector. If we now subtract this vector from the position, we will obtain
the desired position behind the model.
Vector3 offsetPlayer1 = new Vector3(0, -5, 20);
offsetPlayer1 = Vector3.TransformNormal(offsetPlayer1, player1.localWorld);
Vector3 pivotPlayer1 = player1.position - offsetPlayer1;
Now we have the position where we want the camera to be. We can use the model's position for the camera's lookAt. The problem with this is that the camera's movements would be rather "rigid", and we don't want it to seem that the character
and the camera are attached. To solve this, we will add a simple interpolation between the camera's current position and the position where it should be. This way, the camera will move smoothly and it will eventually get to the right position.
Position -= (Position - pivotPlayer1) / 10;
View = Matrix.CreateLookAt(Position, player1.position, Vector3.Up);
As you can see, we divided the distance between the pivot, which is where the camera should be, and the model's position by 10. We then make the camera's position advance towards the pivot's in steps that are 1/10 of the current distance between
them. This will create an interesting effect, since it will slow down as the distance gets smaller, and we will have the feeling that the camera's movement accelerates and decelerates.
Fighting game camera
In games like Tekken or Budokay, both players always appear on the screen, so the camera zooms in or out depending on the distance between players.
First thing we want to do is to find out where the camera should point at. The camera should look at a point in between both players, and to calculate this we have to add the model's position vectors and divide the result by 2.
Vector3 middle = (player1.position + player2.position) / 2;
To calculate the camera's position, we will first have to calculate the plane where the models are and then we can set the camera with the plane's normal.
Let's caulculate one of the player's vector:
Vector3 playersVector = player1.position - player2.position;
Now we can get the vector product of this vector and the Vector3.Up, and use it to calculate the normal vector of the plane:
Vector3 normal = Vector3.Cross(playersVector, Vector3.Up);
normal = Vector3.Normalize(normal);
We now calculate a value, which changes depending on the distance between players, and multiply it by the normal:
float offsetFactor = playersVector.Length() + 50;
Position = middle - (normal * offsetFactor);
Now we have all we need to update our camera's View matrix:
View = Matrix.CreateLookAt(Position, middle, Vector3.Up);
An example of these cameras:
Traslated by Juliet R. Moreiro Bockhop
Created by Javier Cantón Ferrero.
MVP XNA-DirectX 2007/2009