Consiste en una copia exacta, en cuanto a posición relativa, escala y rotación, de todos los objetos (a excepción de cámaras, luces y empties), colocada por debajo de los objetos “originales” en la misma escena “escena_principal”, por motivos que se explican más adelante. Esta copia no se utiliza en la implementación más básica del mini-mapa, sino que será la base de las mejoras visuales que se introducen en el apartado 6.4 (página 119), al proporcionar la independencia entre el mini-mapa y la escena necesaria para poder eliminar sombras y texturas, introducir un icono en lugar de la pelota y controlar ambos por separado.
Se ha decidido que, para facilitar su manejo desde Python, y favorecer la propia función del mini mapa, los objetos copiados deben presentar las siguientes características:
- En cuanto a su forma y colocación relativa son una copia exacta de todos los que intervienen en el juego, situada en la misma escena (“escena_principal”). Su posición absoluta está desviada 1000 unidades de medida de Blender en la dirección negativa del eje Z respecto a los objetos “originales”. Es decir, la copia de una pared cuyas coordenadas XYZ sean, por ejemplo, [5,10,2], se colocará en [5,10,-998] (ver Figura 10).
- El nombre de dichas copias consiste en el del objeto al que representan más la terminación “_mapa” añadida al final.
- El material es de tipo “Shadeless” en todos los casos, ya que no es deseable que la luz afecte al mini-mapa. El color “Diffuse” es el mismo que el del material del primer slot
de materiales del objeto al que representa. Los casos especiales, como el del objeto protagonista, se pueden tratar a parte.
- El tipo físico de todas las copias es “Static”. Las copias que representan a objetos cuyo tipo físico es distinto de “Static” tienen una propiedad de juego llamada “dinamico” con valor “1”.
La decisión de colocar la copia en la misma escena, que rompe con la idea de separación de conceptos (por la cual debería colocarse en la escena “escena_mapa” o en otra nueva) ha estado condicionada por el script que se ha diseñado para realizarla, explicado a continuación. Colocar las copias en una escena diferente requiere una complejidad mucho mayor, y se ha considerado que ni el pequeño aumento en comodidad que proporciona ni el mantener la coherencia con el resto de la organización lo justifican. En la práctica, el único inconveniente derivado de colocar los objetos nuevos en la misma escena es la necesidad de “bajar” hasta ellos en caso de que fuera necesario hacer algún retoque, lo cual se puede atajar usando dos ventanas simultáneamente, una para modificar los objetos originales y la otra para hacerlo con las copias.
La decisión de colocar la copia 1000 unidades por debajo ha sido relativamente arbitraria: se ha puesto a una distancia suficiente como para que no haya interferencias entre objetos de ambos escenarios y que la copia quede fuera del alcance de visión de la cámara “camara_principal”, pero no demasiado grande para minimizar la incomodidad comentada anteriormente.
En la Figura 10 aparece una captura de pantalla de Blender donde se muestra una posible posición relativa entre los objetos originales y sus copias.
Figura 10. Posición de los objetos del juego (arriba) y sus copias (abajo), usadas en el mini-mapa.
Implementación y control del mini-mapa de orientación
Como se ha comentado, durante la realización de este proyecto, dado que la réplica en sí es un proceso tedioso y propenso a causar errores, se decidió diseñar un script (llamado “crear_mapa.py”) que la lleva a cabo automáticamente. Aunque dicho script queda fuera del ámbito del proyecto, ya que se basa en los módulos de la aplicación (ver apartado 3.3, página 20), a continuación se explican brevemente las acciones que realiza, y el código completo se ha incluido en el Anexo I.
- En primer lugar se importan los módulos necesarios, y se crean e inicializan las variables. Los nombres de la escena y el objeto protagonista, así como la altura a la que se colocan las copias de los objetos, se definen como variables de manera que el
script pueda ser adaptado con facilidad a otros escenarios o necesidades.
- Posteriormente se eliminan todos los objetos relacionados con el mapa que pudieran existir anteriormente (se distinguen comprobando si su nombre termina en “_mapa”). Este paso permite que el script pueda usarse además para actualizar el mapa, cuando se añadan, quiten o modifiquen objetos que intervienen en el juego. Aunque probablemente podrían usarse técnicas que actualizaran sólo los objetos necesarios en lugar de eliminar todos y volver a crearlos, al no ser éste el objetivo del proyecto, y dado que el tiempo empleado en realizar la copia no se considera importante (es del orden de décimas de segundo en el fichero de ejemplo), se ha optado por seguir la vía más simple y directa.
- Después se entra en un bucle “for” que recorre todos los objetos de la escena, y se comprueba si tienen asociado un material, en cuyo caso se copiarán (de esta manera se evita copiar objetos innecesarios o incluso perjudiciales, como lámparas, empties o cámaras). Si corresponde duplicarlos, se hacen las siguientes operaciones:
• Se crea un nuevo objeto, cuyo nombre es el mismo que el del objeto original con la terminación “_mapa”, y su estructura es una copia de la del objeto original.
• El objeto recién creado se asocia a la escena “escena_principal”.
• La escala y rotación del nuevo objeto se igualan a las del original. La localización se iguala la del original más el desvío vertical correspondiente (variable definida al principio del script). Si el desvío es de 1000 unidades, la copia de una pared cuyas coordenadas XYZ sean, por ejemplo, [5,10,2], se colocará en [5,10,-998] (ver Figura 10).
• A aquellos que representan a objetos susceptibles de moverse durante el juego se les añade una propiedad, que se usará posteriormente para saber que deben ser actualizados en cada cuadro.
• Se eliminan todos los materiales del objeto nuevo, y se le asigna uno solo, del mismo color que la propiedad “Diffuse” del primer material del objeto original, y de tipo “Shadeless”, para que no se vea afectado por la luz, lo cual no es deseable en un mapa. El material que se asigna debe crearse previamente
o, si ya existía, recuperado de la lista de materiales. La comprobación de si un material existe o es necesario crearlo se hace basándose en su nombre, que contiene las componentes de su color. Como la creación/recuperación de materiales es necesaria en otros puntos del script, se ha colocado dentro de la función “obtener_material”. Esta función toma como parámetro un color y busca en la lista de materiales si existe alguno con el nombre correspondiente; si es así devuelve una referencia al mismo, en caso contrario lo crea y devuelve la referencia correspondiente.
- A continuación se crea la cámara que captará las imágenes, configurando su lente como “Orthographic”. Aunque su posición se controlará en tiempo real, y por tanto no es importante colocarla en ningún punto en concreto, se hace en el origen de coordenadas y a cierta altura sobre el resto del mapa.
- Por último se sustituye el objeto que representa al protagonista (una esfera en este caso) por otro que, visto desde arriba, indique con mayor claridad su posición y dirección, como por ejemplo un cono rotado convenientemente. Se le asigna un material de un color diferente del resto de los presentes en el mapa, de forma que se distinga con claridad (este material se crea aprovechando la función mencionada anteriormente).