5. CONTROL DE LA CÁMARA
5.3. Seguimiento básico del objeto protagonista
5.3.1. Control de la posición vertical
Como se ha comentado anteriormente, el hecho de que la cámara sea un sólido rígido conlleva que se ve afectada por la gravedad, lo que hace necesario intervenir para mantener estable su posición vertical.
La solución más lógica y simple a priori sería modificar su posición en cada cuadro, mediante una línea del tipo: camara_principal.worldPosition[2] = altura_correspondiente. Sin embargo, esto resulta en que la cámara se desplaza continuamente hacia abajo, muy lentamente. Esto probablemente se deba a un conflicto entre la actuación del motor físico, que calcula la velocidad debida a la gravedad, y el establecimiento de la posición manualmente.
El mismo comportamiento se repite si en lugar de definir la posición se aplica una velocidad vertical nula, mediante: camara_principal.setLinearVelocity([n,0,n], 1)
(Recuérdese la disposición de los ejes locales de las cámaras, Figura 8). Por tanto tampoco este método es viable.
La manera más simple de mantener la cámara en la misma posición vertical es combinar los dos métodos anteriores. Si se establece una posición determinada, y acto seguido se hace nula la velocidad en el eje vertical, la cámara no se mueve.
Sin embargo, ya que en los apartados donde intervenga el control manual (con el ratón) en vertical será necesario efectuarlo aplicando velocidades, es decir, se aplicará una velocidad vertical distinta de 0, en este caso se hace de la misma manera: se usa solamente el método “setLinearVelocity”, aplicando la velocidad vertical necesaria para contrarrestar el efecto de la gravedad.
El valor que debe tomar dicha velocidad vertical se calcula siguiendo el mismo principio que en otros apartados: se busca una relación óptima entre el mismo y la/las magnitudes de las que se desea que dependa, mediante operaciones matemáticas simples. En este caso, la velocidad vertical a aplicar se relaciona con la diferencia en cada momento entre la posición vertical de la pelota y la que debería tener.
Hay que tener en cuenta la distribución de los ejes del objeto sobre el que se actúa, para hacer posibles cambios de signo o dirección. En este caso se puede razonar como sigue: la posición vertical deseada para la cámara, que en principio será estática, siempre es mayor que la que tiende a adoptar en cada cuadro, ya que la gravedad la empuja hacia abajo. Por tanto la diferencia entre ellas (deseada – actual) es positiva. El efecto de la velocidad aplicada debe ser contrario al de la gravedad; como ésta empuja a la cámara hacia el sentido negativo del eje Y, la velocidad debe aplicarse en el positivo.
Por otra parte, si fuera necesario hacer descender expresamente a la cámara la posición deseada sería menor que la actual, con lo cual la diferencia menor que cero, y la velocidad a aplicar en el eje Y debería ser también negativa. Existe por tanto una correspondencia entre el signo de dicha diferencia y el de la velocidad necesaria, con lo cual no habrá que tratar ambos casos por separado.
Sólo resta decidir cómo hay que transformar la diferencia entre posiciones para que la velocidad resultante sea adecuada. Esto se hace simplemente probando diferentes operaciones. La más sencilla, suficiente en este caso, es la multiplicación por un determinado factor. En otras ocasiones, que se estudiarán posteriormente, hará falta adaptar los rangos de variación de las magnitudes implicadas, o modificar la función de transferencia. Destacar que no hay una sola manera de establecer la relación. De hecho el cómo se haga determina el comportamiento resultante.
En este caso, como se ha indicado, la velocidad vertical aplicada consiste en la diferencia entre la posición vertical deseada de la cámara y la actual multiplicada por un determinado factor. Este factor, dentro de su rango válido, determina la rapidez con la que se consigue la posición deseada. Debe ser lo suficientemente grande como para que la velocidad aplicada contrarreste a la gravedad, y lo suficientemente pequeño como para que no se produzcan inestabilidades.
En el Fragmento de código 13 aparece el ejemplo más sencillo, que simplemente mantiene la posición vertical de la cámara estática en todo momento. Nótese como en este caso la posición deseada de la cámara es la que tiene inicialmente. Se recomienda ejecutar el archivo “demo_control_pelota.blend”, y probar con diferentes valores del factor anterior, viendo su efecto en cada ocasión sobre la velocidad aplicada y la posición de la cámara. Para ello, el controlador “Python” correspondiente debe estar configurado para lanzar “control_camara_1.main”, y en este módulo deben estar anulados todos los bloques de código de la función “main” excepto el primero.
from bge import logic
escena_principal = logic.getCurrentScene()
camara_principal = escena_principal.objects['camara_principal']
altura_camara_inicial = camara_principal.position[2]
def main():
altura_camara_actual = camara_principal.position[2]
altura_camara_deseada = altura_camara_inicial velocidad_vertical = 2 * (altura_camara_deseada -
altura_camara_actual)
camara_principal.setLinearVelocity([0,velocidad_vertical,0],1)
Fragmento de código 13. Aplicar velocidad vertical a la cámara para contrarrestar el efecto de la gravedad.
Un planteamiento algo más complejo, y que será el definitivo, es establecer la posición de la cámara en función de la del objeto protagonista, de manera que reaccione a sus posibles
Control de la cámara
cambios de altura. En este caso la altura deseada es la de la pelota más la diferencia de altura entre ella y la cámara que haya inicialmente, cálculo que habrá que hacer al principio de la ejecución. El resto del razonamiento es análogo al del caso anterior, incluyendo el criterio de símbolos.
En el Fragmento de código 14 aparece el código que habría que cambiar o añadir (se obvia la lógica que no cambia respecto a fragmentos de código anteriores) para conseguir este comportamiento. Si se ejecuta el fichero de ejemplo, activando el siguiente bloque de código y desactivando el anterior, se observará cómo efectivamente la cámara se mueve hacia arriba y abajo cuando la pelota salta. La rapidez con la que se adapta a sus movimientos está determinada por el factor que multiplica a la diferencia de alturas, 5 en este caso.
# Resto de asignaciones...
pelota = escena_principal.objects['pelota']
altura_camara_pelota_inicial = camara_principal.position[2] -
pelota.position[2]
def main():
altura_camara_actual = camara_principal.position[2]
altura_camara_deseada = pelota.position[2] +
altura_camara_pelota_inicial
velocidad_vertical = 5 * (altura_camara_deseada -
altura_camara_actual)
camara_principal.setLinearVelocity([0,velocidad_vertical,0],1)
Fragmento de código 14. Determinar la posición vertical de la cámara en función de la del objeto protagonista.
Nótese cómo, en los dos casos anteriores, se han basado los cálculos que se hacen en cada cuadro en la situación de la escena al empezar la ejecución. Esto conlleva que se pueden llevar a cabo modificaciones manuales en la escena que se reflejarán en el juego sin la necesidad de cambiar el código. Por ejemplo, si antes de lanzar el juego se coloca la cámara en una posición más elevada, esa será la posición objetivo que se tienda a adoptar durante el mismo. Esta manera de proceder se intentará seguir siempre que sea posible.
En el fichero de texto aparece un tercer bloque de código, llamado “Calcular velocidad vertical (lógica definitiva)”, equivalente al anterior excepto por la última línea, que se ha eliminado. Este bloque se deberá activar (y desactivar el anterior) más adelante, cuando se implemente la velocidad lineal, para evitar que se aplique un valor nulo a la misma. Sería suficiente con eliminar la línea que aplica la velocidad, pero se ha considerado más claro repetir el bloque entero.