jueves, 13 de octubre de 2011

Utilización de variables y constantes

Todos los lenguajes de programación poseen elementos que nos ayudan a estructurar y flexibilizar el código que desarrollamos.
Dos de los elementos esenciales son
  1. Las variables
  2. Las constantes 
Una definición "petarda" de lo que es una variable podría ser:
  • Es un elemento que apunta a una direccion de memoria y que es capaz de escribir y de leer en y desde ese punto de memoria..
Pero a los efectos prácticos podemos establecer que
  • Una variable es una palabra que ponemos en el código, a la que podemos asignar valores y que nos puede devolver el valor que contiene o le hemos asignado.
  • Una constante es lo mismo que una variable pero con la diferencia de que una vez que se le asigna un valor, éste no debería cambiar (veremos que LSL en esto tiene sus peculiaridades) .
Para poder utilizar en LSL una variable hay primero que declararla.



Declarar una variable
En la entrada anterior indicamos cómo se declaran las variables, aquí lo haremos de forma más pormenorizada.
Ya decíamos que para declarar una variable, hay que escribir su nombre precedido del tipo de dato que va a contener
Recordemos nuestro primer script

  default
     {
         state_entry()
         {
             llSay(0, "¡Hola, Avatar!");
         }

         touch_start(integer total_number)
         {
             llSay(0, "Tocado.");
         }
     }


Si nos fijamos podemos ver que se envían dos mensajes distintos:
  1. ¡Hola, Avatar!
  2. Tocado. 
Los mensajes que se muestran en el chat son siempre de tipo texto.
Para especificar que un trozo de código contiene un texto, se escribe entre comillas dobles. Es lo que se llama un tipo de dato string.
Voy a escribir un script que haga exactamente lo mismo pero que en vez de enviar directamente el texto a mostrar, utilice unas variables que contengan ese mismo texto.
Observa el siguiente código

  string mensajeEntrada;
  string mensajeTocado = "Tocado.";
 
  default
     {
         state_entry()
         {
            
mensajeEntrada = "¡Hola, Avatar!";
             llSay(0, mensajeEntrada);
         }

         touch_start(integer total_number)
         {
             llSay(0,
mensajeTocado);
         }
     }

 En la primera línea definimos la variable mensajeEntrada como de tipo cadena de texto string.
  string mensajeEntrada;
Solo por definirla ya contiene un valor, el valor por defecto, en este caso lo que se llama la cadena vacía "". Más tarde, en el manejador del evento entry del estado default, se le asigna el texto:
    mensajeEntrada = "¡Hola, Avatar!";
En la segunda línea declaramos la variable  como también de tipo string y simultáneamente le asignamos el valor Tocado.
  string mensajeTocado = "Tocado.";
La forma de asignar un valor a una variable es sencilla; se utiliza el operador  =   de esta manera:
      nombreDeVariable = NuevoValor;
Como en la mayoría de los lenguajes, hay que tener cuidado de que el valor asignado a la variable sea del mismo tipo que la propia variable, o nos daría un error al compilar.
Luego veremos los diferentes tipos de variables que podemos manejar, pero adelanto que si por ejemplo a una variable de tipo número entero intentamos asignarle un dato tipo cadena nos dará un error, aunque esa cadena de texto contenga aparentemente un número.
Por ejemplo esta línea nos daría un error:
     integer numeroEntero = "2";
En cambio esto sería correcto:
     integer numeroEntero = 2;
Algunos lenguajes como el antiguo Visual Basic son más flexibles en eso e intentan, por su cuenta, interpretar lo que el programador ha querido hacer al equivocarse, lo que puede crear más problemas que soluciones.
Fijémonos en la sutil diferencia entre las dos líneas:
En la primera el 2 lo hemos puesto entre comillas, con lo que le indicamos al compilador que ese número 2 debe tratarlo como si de una cadena de texto se tratara y por tanto el compilador "se queja" diciéndonos que el valor es incorrecto para esa variable.
En la segunda asignamos de forma correcta el valor 2 a la variable.
Fijémonos ahora en el mensaje de error Type mismatch (se puede traducir como No coinciden los tipos) nos está indicando precisamente eso, que los tipos no son coincidentes ya que la variable declarada numeroEntero espera un número entero y lo que tratamos de asignarle es una cadena de texto.
Ese mensaje de error nos aparece en la ventana inferior de la pantalla de edición, y además nos indica dónde ha encontrado el error, en este caso en la columna 28 de la fila 0
      (0,28)  :  ERROR  :   Type mismath.

Constantes
Por definición una constante es un dato asignado a un identificador y que no va a cambiar durante la ejecución del script.
En LSL las constantes se declaran con variables, de hecho no existe un tipo de dato al que una vez le asignemos su valor no pueda ser cambiado en el curso del código, como así ocurre en otyros lenguajes.
Yo personalmente cuando defino constantes, lo suelo hacer justo al principio del script y así son accesibles por todo el código.
Para que no haya lugar a dudas suelo definirlas con mayúsculas, tal y como lo hace el propio entorno de desarrollo de LSL.
    integer NUMERO_PI = 3.141593;  // Así defino una constante
    integer diasMes = 31;          // Así defino una variable
 LSL tiene definidas un gran número de constantes, que normalmente recogen datos habituales de uso, como valores para los prámetros de funciones que afectan a las propiedades de los objetos...
Estas constantes se pueden utilizar directamente sin declararlas ni reinicializarlas.
Ejemplo de constantes definidas por LSL:
       PI, PI_BY_TWO, ALL_SIDES, ATTACH_NOSE, ...
Cuando hablemos de las funciones implentadas en LSL tendremos ocasión de conocer las más habituales.


Tipos de datos
 Con los scripts podemos manejar una amplia variedad de datos, algunos son evidentes como los ya comentados cadena de texto (string) o número entero 8integer) pero otros son más complejos y no tan claros.
Veamos qué tipos de datos es capaz de manejar LSL.

LSL cuenta con 7 tipos de datos:

    integer:
  • Números enteros que pueden tomar valores entre -2,147,483,648 y 2,147,483,647. Los datos enteros pueden escribirse tanto en base  decimal (forma natural humana de escribir) como en hexadecimal (forma más "natural" de manejo de datos para un PC por agrupación de bits de 4 en 4)
    • Entero en forma decimal 2011
    • Mismo valor entero en forma hexadecimal 0x7DB.
Para introducir un valor en formato hexadecimal se escribe un 0 seguido de una x y a continuación el valor (el formato hexadecimal utiliza la base 16 con números del 0 al 9 y a continuación como dígitos letras de la A a la F) No os preocupéis si no entendéis esto, lo utilizaremos pocas veces y lo expongo a título de información.

    float:
  • Números de coma flotante pertenecen al campo de los números reales y pueden tomar valores entre ±1.175494351E-38 y ±3.402823466E+38 incluyendo el 0. Como podemos ver el margen es muy amplio tanto en valores grandes como en valores minúsculos, negativos y positivos.

    vector:
  • Contiene tres números de tipo float en formato <x, y, z>
Como veremos más adelante, varias propiedades de los prims como son posición, tamaño, color y rotación, así como para las rotaciones de Euler o de Tait-Bryan que utilizan matrices de tres elementos.
Podremos comprobar que los vectores tienen un amplio campo de uso por lo que aprenderemos a crearlos y a operar con ellos.

    rotation:
  • Contiene cuatro números de tipo float en formato <x, y, z, a>
Se suele llamar también Cuaternio. Su aplicación más generalizada es para el control de un tipo especial de rotaciones que necesitan una matriz de 4 elementos, por ejemplo se pueden utilizar para el control del movimiento de vehículos, brazos mecánicos etc...
Su uso es habitual en el control de los movimientos de objetos, aunque requieren un cierto nivel de conocimientos matemáticos para sacarles un buen partido. No obstante veremos algún ejemplo práctico con ellos.

key:
Son las claves UUID (Universal Unique Identifiers) Internamente manejan cadenas de 128 bits (un bit es un número que puede adoptar el valor 0 ó 1.
Se representan mediante números hexadecimales, como hemos dicho con dígitos que van del 0 a la letra F.
Cada dígito hexadecimal suministra 4 bits por lo que se necesitan:
128/4 = 32 caracteres con lo que si le sumamos los 4 caracteres guión que actúan como separadores, hace que sea una cadena de 36 caracteres.
Esto podría ser una clave UUID
          "01234567-89ab-cdef-0123-456789abcdef"
Como veremos más adelante, una key se maneja de forma semejante a como se maneja una cadena string.
Todos los objetos, avatares, texturas, animaciones… se pueden identificar por su clave UUID.


   string:
  • Son cadenas de caracteres cuyo tamaño viene limitado por la capacidad de manejar memoria del propio script en el que están incluidas.
Digamos que para usos “normales” tienen una capacidad “suficiente”.
Su manejo es similar a como se manejan con el lenguaje C.
Existen varias funciones especiales suministradas por el propio lenguaje LSL para su manejo y manipulación, aparte de funciones desarrolladas por los propios usuarios.

   list:
  • Podríamos decir que son colecciones capaces de contener una secuencia de cualquiera de los datos definidos anteriormente.
  • Son como un saco que lo admite casi todo, con la salvedad de que no es capaz de contener otras listas.
  • LSL no incluye un tipo de estructura muy habitual en otros lenguajes, los arrays o matrices de datos. Las listas pueden ser una alternativa a los arrays, presentando frente a éstos ventajas e inconvenientes.
En realidad LSL no cuenta con ningún tipo de estructura dinámica, así que deberemos ingeniárnoslas con las listas para emularlas.
Una lista se define escribiendo entre dos paréntesis cuadrados los datos, separados entre sí por comas.
Veamos ejemplos:
list participantes = ["Antonio", "Pilar"];
Aquí hemos declarado la variable participantes como de tipo list y la inicializamos inmediatamente con dos nombres.
Veamos otro ejemplo
list avatares;
avatares = ["Ana Resident", "2011-11-18", "Leon jewell", "2008-09-03"]
Aquí hemos declarado la variable avatares y a continuación la inicializamos con lo que podría ser nombres de avatares y su fecha de nacimiento en SL.
            Como hemos comentado las listas pueden contener datos heterogéneos.
Veamos el siguiente ejemplo:
list objetos;
objetos = ["Pelo", 157, 0.25, "Gafas", 50, 0.33];
La lista objetos podría incluir el nombre de dos objetos, su precio y el tanto por uno de comisión para el fabricante.
  • LSL incluye funciones para acceder a cada elemento de la lista, pudiendo averiguar antes de obtener el dato, el tipo al que pertenece.
  • Adicionalmente existen funciones predefinidas incluso para el manejo de listas de forma global o parcial.
  • Cuando explique el uso de las listas trataré de pormenorizar estas funciones.

En la próxima entrada explicaré más detalladamente los temas relacionados con la declaración de variables, así como su alcance en las diferentes secciones del código.

No hay comentarios:

Publicar un comentario