English Version

Tipos de Cámaras

Este artículo me propuse hacerlo debido a que mucha gente me preguntaba cómo hacer algunos tipos de cámara muy usados, entre ellos una cámara en 3ª persona y una cámara típica de un juego de lucha.

Con este artículo aprenderás a crear estos dos tipos de cámara:

Cámara 3ª Persona

Lo primero es saber a qué tipo de cámara me refiero, con esta cámara nos referimos a la típica cámara de un juego de vehículos (Need For Speed) o juegos en los que puedes ver la espalda del protagonista (Tomb Raider).
Vamos a explicar ahora teóricamente como se ha hecho. Lo primero es tener la posición de tu personaje y hacia dónde está mirando. Esta información la podéis sacar directamente de la matriz LocalWorld de dicho modelo.

Vector3 position = new Vector3(localWorld.M41, localWorld.M42, localWorld.M43);
Vector3 lookAt = new Vector3(localWorld.M31, localWorld.M32, localWorld.M33);


Con estos datos podríamos calcular un punto que se encuentra detrás del modelo, ya que podríamos restarle a la posición el vector lookAt normalizado y multiplicado por un valor. Para normalizar un vector tenemos el método Vector3.Normalize.

TerceraPersona.png

Pero existe una forma más rápida de hacer esto mediante el método Vector3.TransformNormal, en la que sólo tenemos que configurarnos un vector con el offset que le queremos aplicar a la posición y nos devolverá el vector que restado a la posición del modelo será la posición deseada detrás del modelo.

Vector3 offsetPlayer1 = new Vector3(0, -5, 20);
offsetPlayer1 = Vector3.TransformNormal(offsetPlayer1, player1.localWorld);
Vector3 pivotPlayer1 = player1.position - offsetPlayer1;


Con esto ya tendríamos la posición en la que debe estar la cámara, y como lookAt a la cámara le pasaríamos la dirección del modelo, por ejemplo. ¿Cuál es el problema que tiene esto tal y como está? Que los movimientos de cámara serían muy “rígidos” y nosotros queremos que parezca que la cámara y nuestro protagonista no están “anclados” uno al otro. Para ello vamos a añadir una simple interpolación entre la posición actual de la cámara y la posición en la que debería estar. De esta forma la cámara se moverá con suavidad e irá adquiriendo poco a poco la posición en la que debe estar.

Position -= (Position - pivotPlayer1) / 10;
View = Matrix.CreateLookAt(Position, player1.position, Vector3.Up);


DivideDistance.png

Como se puede ver hemos dividido la distancia entre el pivot que sería donde debería estar la cámara y la posición del modelo entre 10, y lo que hacemos es avanzar la posición de la cámara hacia la del pivot una décima parte de la distancia que hay actualmente. Esto provocará un efecto muy curioso ya que si esta distancia es grande la décima parte será grande, y conforme la distancia va disminuyendo la décima parte tambíen. Con ello conseguimos una sensación de aceleración y desaceleración en los movimientos de nuestra cámara.

Cámara lucha

Veamos ahora como haríamos para crear una cámara de un juego de lucha. Este tipo de cámaras tipo Tekken o budokay se caracterizan porque los dos jugadores siempre aparecen en pantalla por lo que la cámara se acerca y aleja dependiendo de la distancia entre los jugadores.
¿Cómo podemos hacer esto? Lo primero será calcular hacia dónde debe mirar la cámara, que debe ser el punto medio entre los dos modelos. ¿Cómo podemos calcular el punto medio entre dos modelos en el espacio? . Pues es tan fácil como sumar los vectores de posición de los modelos y dividir el resultado entre 2.

Vector3 middle = (player1.position + player2.position) / 2;


FightLookAt.png

Para el cálculo de la posición de la cámara tendremos que calcular el plano en el que se encuentran los dos modelos y luego colocaremos la cámara siguiendo la normal a dicho plano.

Bien, lo primero será calcula el vector que va desde un player:

Vector3 playersVector = player1.position - player2.position;


Después calcularemos el producto vectorial entre este vector y el Vector3.Up para calcular el vector normal al plano formado por estos dos vectores:

Vector3 normal = Vector3.Cross(playersVector, Vector3.Up);
normal = Vector3.Normalize(normal);


Y por último sólo queda calcular un factor que multiplicaremos por dicha normal según la distancia a la que se encuentren nuestros jugadores:

float offsetFactor = playersVector.Length() + 50;
Position = middle - (normal * offsetFactor);


CameraFight.png

Y ya tenemos todo lo necesario para actualizar la matriz View de nuestra cámara:

View = Matrix.CreateLookAt(Position, middle, Vector3.Up);


Aprende a poner en práctica todos estos conceptos con este Ejemplo


Created by Javier Cantón Ferrero.
MVP XNA-DirectX 2007/2009
MSP 2006/2008
Date 28/07/2008
Web www.codeplex.com/XNACommunity
Email javiuniversidad@gmail.com
blog: mirageproject.blogspot.com

Last edited Aug 17, 2008 at 4:24 PM by khronos, version 12

Comments

pery Mar 21, 2009 at 2:05 PM 
Pero que facil es cuando te lo explican ;-) Gracias.