• No se han encontrado resultados

Uso de coordenadas globales

5. CONTROL DE LA CÁMARA

5.8. Movimiento básico en vertical usando el ratón

5.8.4. Uso de coordenadas globales

Al posibilitar el control vertical de la cámara mediante el movimiento del ratón se pone de manifiesto una nueva consecuencia negativa de aplicar la velocidad usando los ejes globales como referencia, que se une a la comentada en el apartado 5.5.4 (página 67).

Como se comentó anteriormente, debido a que ni el eje Y de la cámara es completamente vertical, ni el Z es completamente paralelo al plano horizontal, al aplicar velocidad vertical hacia arriba también se hace hacia adelante ligeramente y cuando se hace hacia adelante también se impulsa hacia abajo.

El problema que aparece en este caso se deriva de la decisión de compromiso que hubo que adoptar al establecer la constante en la ecuación que calcula la velocidad vertical necesaria para mantener la altura original: velocidad_vertical = CONSTANTE * (altura_camara_deseada - altura_camara_actual). Valores pequeños de esta constante permiten que cuando el protagonista se desplaza muy rápido la velocidad vertical no sea capaz de compensar el empuje hacia abajo causado por la componente vertical de la velocidad lineal. En apartados anteriores fue suficiente con aumentar su valor hasta 10 para contrarrestar

Control de la cámara

este efecto, sin embargo al habilitar el control en vertical no es posible hacerlo por los siguientes motivos:

- Si, cuando el sistema automático entra a funcionar, después de no mover el ratón durante 100 cuadros, la cámara está muy elevada, la diferencia entre alturas que determina la velocidad vertical es grande. Si se multiplica por una constante también grande, el movimiento generado es muy brusco.

- Dado que en este caso la velocidad vertical se somete a un suavizado antes de ser aplicada, siempre existe cierto retraso en la respuesta. Este retraso hace que en el momento en que la velocidad aplicada debiera ser nula, por haberse alcanzado la altura objetivo, se siga desplazando. Habrá por tanto una respuesta a este desplazamiento erróneo, que de nuevo se retrasará, volviendo a comenzar el ciclo. La magnitud de esta constante determina si la oscilación, que es inherente al método usado en el suavizado, es perceptible o no. Valores mayores la hacen más notoria, e incluso llevado al extremo la oscilación puede hacerse inestable.

La solución tanto a este problema como al comentado en el apartado 5.5.4 (página 67) (no es posible parar la velocidad lineal cuando es necesario ya que en ella influye la velocidad vertical) es aplicar la velocidad sin apoyarse en los ejes de la cámara.

La base del proceso es similar a la usada en el control del objeto protagonista: se calcula en cada cuadro la dirección global en que cada velocidad para que su efecto sea el deseado. Posteriormente cada vector de dirección se multiplica por la constante correspondiente a cada velocidad, se suman y el resultado se pasa al método “setLinearVelocity”.

Las constantes a utilizar son las que anteriormente se colocaban en cada componente del vector que se pasaba a “setLinearVelocity”, por tanto no es necesario ningún cambio. Las direcciones se calculan tomando como base la orientación de los ejes de la cámara, que se obtiene de su matriz “worldOrientation” (ver apartado 7.8, página 147), eliminando las dependencias entre ellos según sea necesario en cada caso. Para mejorar la legibilidad se extrae primeramente la dirección de cada eje de dicha matriz, almacenándolas en las variables “eje_x_camara”, “eje_y_camara” y “eje_z_camara”. A continuación se detalla el proceso:

- La dirección correspondiente a la velocidad lateral será siempre un vector equivalente al eje X de la cámara, es decir, perpendicular la línea que une la cámara y la pelota, hacia la derecha, y paralelo al plano horizontal.

- La dirección de la velocidad lineal (“direccion_velocidad_lineal”) será, por lo general, un vector con la misma dirección en el plano horizontal que el eje Z de la cámara (y su sentido negativo) pero paralelo a dicho plano, es decir, un vector equivalente al eje mencionado con la tercera componente anulada. De esta manera la velocidad lineal no influye en la vertical. Sin embargo, en los casos donde la inclinación de la cámara sea grande, la dirección de la velocidad lineal no puede ser paralela al plano horizontal, ya que su función es controlar la distancia entre la cámara y la pelota. En estos casos sí es necesario que la dirección de la velocidad lineal sea equivalente a la del eje Z de la

cámara, para que realmente avance hacia ella. Un ángulo de elevación grande solamente se puede dar si la pelota se desplaza rápidamente en vertical o si el usuario mueve la cámara con el ratón; por tanto, la decisión de qué dirección escoger para la velocidad lineal dependerá de que la componente vertical de la velocidad de la pelota sea mayor o menor que un valor dado (el 0 no es práctico porque siempre se producen pequeñas variaciones) y del tiempo que el usuario lleva sin mover el ratón en vertical. Por otra parte, la influencia que la velocidad lineal ejerce sobre la vertical sí podría considerarse beneficiosa cuando la pelota avanza hacia atrás, en cuyo caso provoca que la cámara se eleve ligeramente antes o mientras gira para adoptar la nueva dirección. Para habilitar esta distinción es suficiente con igualar

“direccion_velocidad_lineal” a “-eje_z_camara” cuando la magnitud de la velocidad lineal calculada sea negativa, es decir la cámara avance hacia atrás. Sin embargo esto implica una pérdida de control sobre la velocidad vertical, que en apartados

posteriores, donde se tienen en cuenta los choques contra obstáculos en todas las direcciones, resulta perjudicial. Por tanto, aunque en el ejemplo sí se incluye, en los siguientes apartados no se hará. En la práctica podría usarse en escenarios sin obstáculos elevados, o donde no se tengan en cuenta, o modificar la lógica para considerar la presencia o cercanía de obstáculos además del sentido de la velocidad lineal.

- La dirección de la velocidad vertical debe ser, en general, equivalente a la del eje Y de la cámara, de manera que siempre la impulse correctamente. Si no se posibilitara el movimiento en vertical mediante el ratón la velocidad para mantener la posición podría aplicarse sólo en el eje Z, de manera que no influyera en la lineal. Sin embargo, dado que la cámara se mueve en una esfera alrededor del protagonista, la velocidad vertical (al igual que la horizontal) debe ser tangente a la misma, es decir, equivalente al eje Y. Al usar esta dirección para la velocidad vertical se sigue interfiriendo en la lineal, y aparece igualmente el problema de no poder detenerla cuando es necesario. Para solucionarlo puede por ejemplo determinarse que cuando se dé la condición que hace parar la velocidad lineal (hay un obstáculo detrás de la cámara) la dirección de la velocidad vertical sea paralela al eje Z.

En el Fragmento de código 36 aparece todo el código necesario para hacer el cambio a coordenadas globales, incluyendo las consideraciones anteriores. El cálculo de los vectores finales debe hacerse después de haber obtenido todas las magnitudes, mientras que el de las direcciones podría en un principio hacerse en cualquier punto del módulo (antes que el cálculo de los vectores). Sin embargo éste se hace al principio, ya que las direcciones se usarán en la parte del control de choques, que se cubre en el apartado siguiente.

Este código aparece en el fichero y módulo de ejemplo (“control_camara_6.py”) entre comillas triples. Para poder usarlo es necesario activar cada uno de los bloques: el cálculo de direcciones en la parte superior (llamado “Calcular las direcciones globales correspondientes a las locales”), el ajuste de las mismas según la velocidad lineal (denominado “Correcciones a

Control de la cámara las direcciones calculadas”) en la parte central, y al final el cálculo de los vectores correspondientes a cada velocidad (“Calcular vectores velocidad”), y la aplicación de la velocidad respecto a coordenadas globales (“Aplicar velocidad total”). Además, se debe anular la línea que anteriormente aplicaba la velocidad respecto a coordenadas locales.

# Asignaciones del nivel superior... def main():

orientacion_camara = camara_principal.worldOrientation.copy()

orientacion_camara.transpose()

eje_x_camara,eje_y_camara,eje_z_camara = orientacion_camara[:]

if cuadros_sin_raton_vertical < 100 or

fabs(pelota.worldLinearVelocity[2]) > 1:

direccion_velocidad_lineal = -eje_z_camara else:

direccion_velocidad_lineal = Vector((-eje_z_camara[0],-

eje_z_camara[1],0)) direccion_velocidad_lineal.normalize() direccion_velocidad_lateral = eje_x_camara direccion_velocidad_vertical = eje_y_camara #Resto de lógica...

if pared_cerca and velocidad_lineal > 0:

velocidad_lineal = 0

# Hacer velocidad lineal independiente de vertical

direccion_velocidad_vertical = Vector([0,0,1])

if velocidad_lineal > 0:

# Elevar cámara al avanzar hacia atrás

direccion_velocidad_lineal = -eje_z_camara #Resto de lógica... vector_velocidad_lineal = -velocidad_lineal * direccion_velocidad_lineal vector_velocidad_vertical = velocidad_vertical_final * direccion_velocidad_vertical vector_velocidad_lateral = velocidad_lateral_final * direccion_velocidad_lateral vector_velocidad_total = vector_velocidad_lineal + vector_velocidad_lateral + vector_velocidad_vertical

camara_principal.setLinearVelocity(vector_velocidad_total,0)

Fragmento de código 36. Aplicación de la velocidad usando coordenadas globales como referencia, gestión de las dependencias entre ejes.