Taller
>> Taller >> Curso De Iniciación A DIV by Wakroo >> Cap. 7: Códigos identificadores.

Bueno, ahora que ya podemos hacer mucho ruido y crear un personaje que detecte los choques con un laberinto, unos enemigos que le atacan y una manera para defenderse ha llegado el momento de empezar a profundizar un poco más. Y el siguiente paso son los códigos identificadores de los procesos (de ahora en adelante, id).

Lo primero de todo, ¿qué es un código identificador? Pues es, simplemente, un número, entero, positivo e impar. DIV le asigna a cada proceso uno de esos códigos identificadores en tiempo de ejecución, por lo que no podemos saber cuáles serán esos números mientras programamos ni tampoco podremos asignarlos o cambiarlos. De todas formas, es muy sencillo obtener ese valor: está almacenado en la variable local id de cada proceso y también es el valor de retorno de las llamadas a procesos.

¿Y qué es un valor de retorno? Pues es el valor que retorna una función. Me explico. Muchas de las funciones y los procesos de DIV devuelven un valor que puede expresar distintas cosas. Por ejemplo, la función collision() devuelve el código identificador del proceso con el que se ha colisionado, de manera que si ponemos variable=collision(TYPE enemigo); tendremos en variable el código identificador del proceso enemigo con el que hemos colisionado. Igual que esta función también tienen retorno todos los load_[...]() (para referirse a ese fpg, wav, map,...), write() (para poder borrar ese texto), sound() (para modificar ese canal de sonido),... y los procesos (su id). Por lo tanto, los valores de retorno son un aspecto importante del lenguaje.

Pero volvamos a lo que estábamos. Los id son fundamentales a la hora de interactuar con procesos, ya que gracias a su id podemos leer y modificar las variables locales de un proceso (las privadas no). Por lo tanto, podríamos mover un proceso desde otro, cambiar su gráfico, rotarlo o hacer cualquier cosa que podamos hacer mediante variables locales. Quiero llamar la atención sobre un pequeño detalle: también podemos haber declarado alguna variable local que usemos como señalizador de lo que tiene que hacer el proceso. De esa manera, podemos, por ejemplo, poner esa variable a 1 cuando choque con el laberinto (para que se mueva más despacio), a 2 cuando atraviese una zona de campos eléctricos (para que vaya perdiendo energía) y a 3 para decirle que está en un túnel de alta velocidad (para que vaya muy rápido pero no permita disparar). La comprobación de la variable para saber qué tiene que hacer lo realiza el propio proceso, pero los cambios en esa variable los hacen otros procesos que tienen acceso a su id.

Solucionemos ahora el problema que teníamos con los disparos y los enemigos que "chocaban accidentalmente". Aunque se podría hacer al revés, vamos a hacer que sea el enemigo el que detecte las colisiones con los disparos. Declaramos una variable privada llamada id2 (o cualquier otro nombre que os diga algo a vosotros; yo uso ése, más que nada porque se parece a id pero no es una palabra reservada del lenguaje). Luego ponemos la siguiente sentencia:

..............IF (id2=collision(TYPE disparo))
..................signal(id2,s_kill);
..................BREAK;
..............END

Analicemos la condición con cuidado. Primero se hace el IF, pero con un cambio: el paréntesis tiene una asignación. Por lo tanto, se asigna a id2 el valor de retorno de la función collision (el código identificador del proceso tipo disparo con el que está colisionando o 0 si no está colisionando con ninguno). Luego se comprueba el valor de id2. En DIV, todas las condiciones impares se consideran verdaderas y las pares falsas (el 0 se considera par). Por lo tanto, si id2 contiene 0 no se ejecutará el IF y si contiene un código identificador, que, por definición, es un número impar, será cierto y se ejecutará.

Una vez dentro del IF tenemos una nueva sentencia: signal. Tiene dos parámetros. El primero es el tipo de procesos a los que afectará (por ejemplo, TYPE enemigo) y el segundo la señal que se le mandará. Existen cuatro señales: s_kill matará al proceso, por lo que su código dejará de ejecutarse y desaparecerá de pantalla para siempre; s_sleep dormirá el proceso, por lo que su código no se ejecutará ni aparecerá en pantalla, pero el proceso seguirá existiendo; s_freeze congelará el proceso, por lo que su código no se ejecutará pero el gráfico seguirá en pantalla (y los demás procesos podrán detectar colisiones con su gráfico); y finalmente s_wake_up, que despertará a los procesos dormidos y congelados de manera que sigan ejecutando su código donde lo dejaron. Además, existen otras cuatro variantes de estas señales, que se consiguen poniendo _tree detrás de la señal (s_kill_tree,...), que actuarán sobre ese proceso y toda su descendencia (ver el capítulo siguiente).

Por lo tanto, el proceso enemigo hace lo siguiente. Mira a ver si ha colisionado con algún proceso del tipo disparo. En caso afirmativo, destruye el proceso disparo con el que ha colisionado usando su código identificador y luego se autodestruye. De esta manera nos aseguramos de que desaparecerán tanto el proceso enemigo como el disparo y evitamos el problema que teníamos en el capítulo anterior.