lunes, 20 de marzo de 2017

Python en Blender Game Engine

Texto por Pablo Parra Iglesias
revisado por Enrique Rendón


La escritura de los scripts se realiza en la ventana Text Editor. Para iniciar la programación hay que seleccionar New para abrir un nuevo script y ponerle un nombre con extensión .py, además, es conveniente que estén marcados los botones que se muestran en la figura 1. 

Al marcar el símbolo que aparece debajo del (1) de la figura 1, se muestra el número de línea correspondiente a la izquierda del código, lo que favorecerá la corrección de código erróneo al leer los errores mostrados en la consola al ejecutar el programa. Al tener seleccionado el símbolo (2) de la figura 1, Blender marca con colores (activando syntax colouring) palabras clave del código como bucles for, sentencias if, importación de módulos o comentarios.

 Figura 1. Script 

 
Para que el script programado pueda operar en Blender Game Engine es necesario que ejerza como controlador en los bloques pertenecientes a la lógica del juego.


Según la finalidad del código y cómo esté implementada la lógica del juego hay que decidirse por uno de los dos modos de uso de los controladores Python.


En el modo Script hay que seleccionar qué fichero .py se va a usar como controlador. Al acceder al fichero, se evalúa todo el código presente en él. Esto será útil para ejemplos sencillos, pero su uso en ficheros más complejos producirá una mayor ineficacia del código puesto que la importación de módulos, la obtención de las referencias a controlador, sensores y actuadores, más las inicializaciones de las variables se realizará en cada iteración del programa; pudiendo llegar a producir un retardo de la velocidad del programa.


El otro método de ejecución es el modo Module. En él solo se hace referencia a una función dentro de un script. Para ello, una vez seleccionado el correspondiente modo, hay que indicar el nombre del script donde se encuentra la función, seguido de un punto, más el nombre de la función a la que se hace referencia. Con este método, solo se ejecuta una vez el código que está fuera de las funciones del script usado como módulo. Este código se emplea, principalmente, para inicializar valores.


Por esto que se ha expuesto, se observa que el método de ejecución modo module es más eficiente, por lo que  se tenderá a usar con mayor frecuencia esté modo.

En la figura 2 se muestra un ejemplo en el que se ha seleccionado el modo módulo (símbolo (2) en la figura), llamando en cada frame a la función suma, que está presente en el script prueba.py. Además conviene marcar la pestaña marcada con el símbolo (3), que se ejecute prioritariamente el código del controlador por delante de los que no lo tengan marcado.

Figura 2. Controlador Python


 Dependiendo de cómo se quiera implementar la lógica del juego, el código Python programado será activado de diferente forma. Si solo se quiere acceder a ese código cuando se den unas condiciones concretas (condiciones que se verificarán por los sensores), entonces el controlador Python se activa mediante los bloques lógicos de los sensores, y solo se accede si cambian las condiciones de activación.


Por otro lado, si la finalidad es que el código controle en todo momento el programa, sin necesidad de que se cumplan unas determinadas condiciones, el controlador se activará mediante un sensor always configurado para que se acceda a él en cada frame. Para ello tendrá que tener marcada la pestaña que se indica en el símbolo (1) de la figura 2. Si el valor de Skip se deja a 0, el sensor always se ejecuta en cada frame. Se podría lanzar el script con menos frecuencia poniendo un valor mayor que cero en Skip.


Para poder acceder a las funciones correspondientes al Blender Game Engine (BGE), es necesario importar primero su correspondiente módulo. Más adelante se hablará en más profundidad de qué módulos particulares hay dentro del módulo BGE. El que más se utiliza dentro del BGE es el módulo logic, correspondiente a la lógica del programa.


Una vez importados los módulos correspondientes, se obtiene una referencia al controlador mediante la función getCurrentController(), correspondiente al módulo logic.


Hay dos formas de importar módulos. Se muestra la comparación en el fragmento de código 1. En la primera se importa el módulo general y, para poder acceder a los módulos particulares, hay que llamar al módulo general seguido del módulo particular más la función a la que se quiere acceder.

El segundo método de importación es indicar desde el principio qué módulos particulares se van a necesitar del módulo general. 

Es conveniente emplear el primer método puesto que, si usando el segundo método se declarase una variable con el mismo nombre de algún módulo particular importado (en este caso logic), se perdería el acceso al módulo.

 
Fragmento de código 1. Importación de módulos



Teniendo la referencia al controlador, mediante el campo sensors perteneciente al controlador, se obtiene una lista de qué sensores forman el programa. El campo actuators hace lo mismo con los actuadores. Para poder obtener el control sobre un determinado sensor o actuador hay que poner entre corchetes y comillas el nombre de ese sensor o actuador determinado. Hay que tener en cuenta también que los identificadores son Case Sensitive, es decir, que diferencian mayúsculas de minúsculas. En el fragmento de código 2 se muestra un ejemplo de esto.



 Fragmento de código 2. Acceso a sensores y actuadores.



En el fragmento de código 3 se muestra cómo acceder a una propiedad del objeto. En este caso la propiedad es un entero que se ha llamado contador. Cada vez que se pulse el teclado, la propiedad contador del objeto aumentará en una unidad.

Hay que tener en cuenta que se llama al script de Python cuando cambia uno de los sensores a los que está conectado, tanto si cambia a verdadero como si lo hace a falso. Atendiendo a esto, en una sentencia del fragmento de código 3 se ha evaluado solo cuando el teclado es pulsado (teclado.positive); de esta forma solo se ejecuta una vez la sentencia posterior

 
Fragmento de código 3. Acceso a una propiedad

Para acceder a otro objeto de la misma escena, es necesario obtener primero una referencia a la escena actual, y después ya se puede acceder al otro objeto. Para ello se emplea la función getCurrentScene() del módulo bge.logic. Para más información, buscar en la API de Blender [1].

En el fragmento de código 4 se muestra un ejemplo en el que, desde un objeto, cada vez que se toca una tecla del teclado, se incrementa en uno la propiedad contador de otro objeto llamado Esfera.



 Fragmento de código 4. Acceso a un objeto

Ejemplo completo aquí acceso_objeto.blend

Para acceder a otras escenas se emplea la función getSceneList() del módulo bge.logic. Una vez obtenida la lista de las escenas cargadas en el motor de juego, se selecciona la escena a la que se quiere acceder. 
El fragmento de código 5 corresponde un ejemplo en el que desde un objeto perteneciente a una escena, se quiere acceder a otro objeto llamado cilindro que pertenece a otra escena llamada Escena2.

 
Fragmento de código 5. Acceso a otra escena

Ejemplo completo aquí acceso_escena.blend
 

No hay comentarios:

Publicar un comentario