=====2. Guía para sobrevivir a la creación de scripts con WME===== Ya hemos visto la primera parte del funcionamiento de WME, hemos mostrado el entorno de desarrollo, y seguro que estas deseando avanzar. Como habrás comprobado, gran parte de la funcionalidad de WME, reside en los scripts, pero: **¿ que son los scripts?** Vamos a empezar desde el principio. Toda la funcionalidad de un software reside en su núcleo. Esto significa que cuando se realiza una acción, el programa debe responder a lo ocurrido. Las acciones pueden ir desde clicks de ratón, hasta el tiempo que pasa desde un instante a otro. Luego ¿que es un script? Pues es un programa donde se define que acciones hay que controlar, y como responder a ellas. Un juego básico en WME estará constituido por múltiples scripts. Por ejemplo, si haces un clic con el ratón sobre una puerta, necesitaras un script que haga que tu personaje diga “La puerta esta cerrada”. A medida que profundicemos en este capítulo, aprenderás muchos “trucos” sobre WME y algo de programación en general, pero empecemos desde el principio. El núcleo de la programación en WME, reside en las instrucciones. Las instrucciones en WME indican como controlar una acción. Tenemos multitud de instrucciones diferentes, desde simples operaciones matemáticas(suma, resta, multiplicación, etc) hasta instrucciones complejas como: Game.ChangeScene(“escena.scene”); Este comando hace que wintermute cambie de escena, pero eso es simplemente un ejemplo, mas adelante abordaremos instrucciones como esta. Empecemos por lo mas básico de la programación(scripting). Empezaremos con algo a lo que llamamos variable. **¿Que es una variable ?** Una variable es un contenedor donde podemos guardar información. En WME( a diferencia de C++) puedes almacenar cualquier tipo de información en tu variable( cadenas de texto, objetos, números,...) muy parecido a como funciona php. **Nota:** C++ y php son dos lenguajes de programación. Es más parte de la programación de WME se basa en C++. Bien como hemos dicho una variable es un contenedor donde guardaremos algo, veamos un ejemplo: var miVariable = “hola mundo”; La palabra var declara una variable local llamada miVariable que contiene la cadena de texto hola mundo. **Nota:** una cadena de texto(String) es un tipo de datos que no es mas que simplemente una cadena de caracteres alfa-numéricos encerrados entre comillas dobles “” . Una vez que hemos creado la variable y le hemos dado un valor(“hola mundo”) podemos llamar al texto hola mundo por ejemplo usando: Game.Msg(miVariable); Esta instrucción lo que hace es mostrar en pantalla el contenido de la variable miVariable, que en este caso será hola mundo. **Primera regla de sintaxis** Como puedes observar, cada instrucción debe terminar con un punto y coma ( ; ). Excepto en varios casos que ya veremos mas adelante. Otra cosa importante, es que WME hace distinción entre mayúsculas y minúsculas, mivariable no es lo mismo que miVariable, ya que en la primera la v esta en minúsculas, y en la segunda no. No olvides esto porque suele ser una de las cosas que a veces dan quebraderos de cabeza. Otra regla importante, es que las variables se declaran solo una vez en cada script, es decir solo usaremos la palabra reservada var la primera vez que vayamos a usar o declarar la variable, las demás veces llamaremos a la variable con su nombre, y nunca poniéndole var delante. Veamos algún ejemplo del uso de variables: var miVariable="hola mundo"; /* esta linea declara una variable llamada mi variable y que contiene el texto hola mundo. */ Game.Msg(miVariable); /* esta linea muestra por pantalla el contenido de la variable llamada miVariable que en este caso, será el texto hola mundo. */ miVariable=1; /* con esta linea guardamos en la variable el numero 1, el texto hola mundo desaparece. */ miVariable = miVariable + 1; /* en esta linea, lo que hacemos es incrementar en 1 el valor de la variable, es decir, miVariable es igual a lo que valía miVariable + 1. */ Game.Msg(miVariable); /* Volvemos a mostrar la variable por pantalla, en este caso veremos el numero 2, ya que es el valor que tiene la variable en este momento. */ miVariable=miVariable * 2; /* Con esta linea lo que hacemos es multiplicar el valor actual de la variable por dos y guardarlo en miVariable.( en este momento, la variable contendría el numero 4). */ miVariable=miVariable / 4; /* Con esta linea lo que hacemos es divir entre cuatro la variable y la guardamos en ella misma otra vez. ( En este caso la variable tiene el valor 4 y si la dividimos entre 4 nos dara el valor 1, por tanto miVariable ahora contendrá el valor 1). */ miVariable=”el resultado es”+ miVariable+ “!”; /* En este caso estamos almacenando en miVariable la concatenacion( union ) del texto el resultado es, con el valor que tenia la variable hasta ese momento( en este caso era 1 ) y un signo de exclamacion al final. ( luego tras esta linea, miVariable contendrá: el resultado es 1! */ Game.Msg(miVariable); /* Volvemos a mostrar por pantalla el contenido de la variable.( En este caso veremos: el resultado es 1! ). */ **Segunda regla de sintaxis** Si queremos comentar algo para nuestro entendimiento o el de los demás, podemos usar doble barra inclunada '/' para comentarios de una sola linea o /* comentario */ para comentarios de varias lineas. Los comentarios no afectan de ningún modo al programa, solo sirven para dejarnos las cosas claras a nosotros o a cualquiera que pudiera coger el código en el futuro.\\ Ejemplos:\\ var a = 1; // declaramos una variable llamada a igual a 1, esto es un comentario de una linea /* esto es un comentario de varias lineas */ **Recomendación:** Siempre intenta llamar a tus variables de una manera que puedas saber lo que contiene. Es gracioso llamar a una variable pepitoGrillo, pero si la llamas así y dentro de 5 o 6 meses miras el código, te preguntaras ¿que es lo que tenia esta variable? Mientras que si le pones un nombre descriptivo sabrás de donde salio esa variable. Por ejemplo si quieres guardar en una variable la hora del día que es en el juego, pues lo más lógico es que llames a esa variable hora, o time, o algo que la describa. Otra recomendación es usar siempre una nomenclatura para las variables, me explico, como WME hace distinción entre mayúsculas y minúsculas hay que tener cuidado con eso, así que para evitarnos problemas podemos nombrar a las variables de una forma concreta, por ejemplo: var MiVariable= 1; // Aquí vemos que Mi y Variable empiezan con mayúsculas. o var miVariable= 1; /* Aquí mi la primera palabra va en minúsculas y las siguientes en mayúsculas */ Esto es recomendable porque cuando volvamos a usar la variable si usamos una estructura, no habrá que ir hacia atrás en el código para acordarte exactamente como lo escribiste. Como viste hemos hablado de algo llamado variable local. La palabra local significa, que esa variable solo es valida en el script donde es declarada. Por ejemplo, imagina que tienes dos scripts que son ejecutados uno tras otro, llamados test1.script y test2.script: **test1.script** var a=10; //declaramos la variable a con el valor 10 Game.Msg(a); // la mostramos por pantalla **test2.script** var a = a +1; //declaramos la variable a con el valor que tenia mas uno. Game.Msg(a); // se muestra por pantalla el valor de a El script test1.script mostrara por pantalla el valor 10. El script test2.script mostrara por pantalla el valor 1. Es común pensar que el script test2.script debería mostrar por pantalla el valor 11, pero esto no es así, debido a que la variable “a” del script test1.script solo se puede usar dentro del script test1.script. Y la variable “a” del script test2.script solo se podrá usar dentro del script2.test Pero entonces, ¿como podemos compartir una variable entre unos script y otros? Para esto usamos otro tipo de variable llamada variable global. Esta variable es declarada usando la palabra reservada global y se puede usar en cualquier script de todo el juego. **Tercera regla de sintaxis** En todos los script donde queramos usar una variable global, debemos declarar esta variable con la palabra reservada global. Veamos el ejemplo anterior con variables globales. **Test1.scrip** global a=10; //declaramos la vaariable global llamada a con contenido igual a 10. Game.Msg(a); // mostramos el valor de a por pantalla. Test2.script global a = a+1; // llamamos a la variable global a y le asignamos el valor que tenia mas 1 Game.Msg(a); // volvemos a mostrar a por pantalla. En este caso el script test2.script mostraria por pantalla el valor 11, ya que estamos haciendo uso de variables globales, y en el script test1.script ya le habíamos dado el valor 10. De esta manera podemos compartir variables entre distintos scripts. **Ojo:** si llamamos a una variable global, solo es necesario llamarla una vez, es decir solo usaremos la palabra global la primera vez que usamos la variable en cada script, posteriormente, la llamaremos por su nombre. Veamos un ejemplo que se nos podría dar a la hora de programar un juego, imagina que tenemos un botón en una escena, y que si lo pulsamos, queremos que se abra una puerta en otra escena diferente. Pues simplemente, crearemos por ejemplo una variable global llamada botón, y le daremos el valor false (falso, variables booleanas). Cuando el jugador pulse sobre el botón, cambiaremos el valor de la variable a true(verdadero). Y en la escena donde queramos que se abra la puerta, llamaremos a la variable global botón y miraremos que valor tiene, si tiene un false(falso), la puerta estará cerrada, si la variable botón tiene el valor true(verdadero), entonces la puerta estará abierta. Y de esta manera podemos hacer que la puerta no se abra hasta que el jugador encuentre el botón. Sobre la variables booleanas, que decir que se usan para algo llamado condiciones que veremos mas adelante, pero básicamente es una variable, que solo puede contener 2 valores, o true(verdadero) o false(falso). Pero lo veremos detenidamente mas adelante. Hemos visto lo básico de las variables, hay mucho mas sobre ellas, pero lo iremos viendo conforme vayamos avanzando. =====2.1 Arrays mágicos===== Antes de empezar a hablar de los arrays, vamos a ver un ejemplo que se podría dar en un juego real. Imagina que tienes una puerta protegida con un panel de código. Tienes que pulsar cuatro números correctos y entonces las puertas se abren. Hay varias formas de hacer esto, veamos un par de ellas. **Mala elección** Con lo visto en el capítulo anterior, probablemente, lo harías creando 4 variables( por ejemplo codigo1, codigo2, codigo3, codigo4) y les distes el valor de los números a pulsar para la combinación correcta. Entonces tendrás que comprobar una a una para ver si coinciden. Parece buena idea, pero esto se hace tedioso y es preferible usar otras alternativas. **Elección complicada** Esta es la forma optima de hacerlo, pero es mas complicada.Puedes usar solo una variable y mediante operaciones matemáticas construir el número a comparar con el que se requiera para abrir la puerta. Bueno es complicada porque no todos somos buenos en matemáticas o ingeniosos para crear las funciones. ;) **Elección acertada** Usa un array. Un array es una variable pero en la que puedes guardar mas de un dato. Imagina un mueble con varios cajones, y en cada cajón se puede guardar un calcetín, pues en el primer cajón guardamos un calcetín rojo, en el segundo uno verde, en el tercero uno amarillo, y así... Cuando queramos el calcetín rojo, iremos al cajón 1 del mueble. Pues esto es una analogía con lo que es un array. En términos técnicos y siguiendo la traducción, imagina un array como un grupo de variables. Puedes hacer referencia a estas variables indexando la posición en la variable que declaramos como array. Con un ejemplo lo veremos mejor. Bien, definamos una variable miArray y 3 casillas. var miArray; miArray[0]=”hola mundo”; miArray[1]=”este es mi primer array”; miArray[3]=”weeeee!!”; Game.Msg(miArray[0]); // imprime hola mundo Game.Msg(miArray[1]); // imprime este es mi primer array Game.Msg(miArray[2]); // imprime weeeee!! Otro ejemplo de acceso al array mediante una variable: var a=1; Game.Msg(miArray[a]); // imprime por pantalla este es mi primer array **Cuarta regla de sintaxis** Para acceder al array lo haremos accediendo a sus posiciones poniendo la posición a la que queremos acceder entre corchetes, precedido del nombre del array. nombreArray[posicionRequerida]; Volvamos al ejemplo del código de la puerta, fácilmente podemos almacenar todo el código en una sola variable, con los valores correctos que el jugador debe pulsar para que la puerta se abra. Por ejemplo: var codigo;//declaramos la variable codigo[0]=5;//guardamos un 5 en la posición 0 codigo[1]=3;//guardamos un 3 en la posición 1 codigo[2]=1;//guardamos un 1 en la posición 2 codigo[3]=0;//guardamos un 0 en la posición 3 De esta manera, tenemos varios valores en la misma variable. Y la óptima pero como ya comentamos, era mediante operaciones podría ser del siguiente modo: var codigo=5;//asignamos 5 a la variable código codigo=codigo-2;// 5-2 = 3 codigo=codigo-2;// 3-2 = 1 codigo=codigo-1;// 1-1 = 0 De esta manera también obtendríamos el código 5310 pero es mas intrincado. Como veis para facilitarnos las cosas, los arrays son muy útiles. Por supuesto, si puedes y eres capaz, puedes usar códigos para la puerta mucho mas complejos, estos solo son ejemplos simples, por ejemplo, puedes hacer que el código cambie según algún evento del la hora que hay en un reloj de la pared, ya es cosa de imaginación. Conforme vallas programando, encontraras muchos usos diferentes para los arrays, la fuerza de los arrays reside en la indexación. Puedes acceder a cualquier valor del array durante la programación, pero lo veremos con un ejemplo. Quizá hayas visto juegos, en los que obtienes distintas respuestas para una misma acción sino fuera así, seria muy aburrido. Bien veamos como solucionarlo usando un array. Incorporaremos una nueva instrucción llamada Ramdom. **Ramdom** es una función que devuelve un número aleatorio dentro de un rango. Hablaremos sobre las funciones mas adelante, por el momento no te preocupes si algo no se entiende, mas adelante se entenderá. var arrayRespuestas; arrayRespuestas[0]=”esta bloqueado”; arrayRespuestas[1]=”no puedo moverlo”; arrayRespuestas[2]=”no hay nada que hacer”; var respuesta = Random(0,2); //número aleatorio entre 0 y 2 Game.Msg(arrayRespuestas[respuesta]); Este script básicamente, lo que hace es que cuando realizamos una acción sobre algo, nos devuelva una respuesta aleatoria desde 3 posibles. Bueno ya hemos visto lo básico de los arrays, mas adelante haremos referencias a ellos para ir viendo las funcionalidades de los scripts en WME. =====2.2 Condiciones ===== A menudo necesitamos saber que esta pasando, volvamos al ejemplo de la puerta que se abre con un botón, necesitamos saber si el botón esta presionado o no. pero ¿como lo comprobamos? Pues tenemos una instrucción condicional( if ) que nos facilitará el trabajo. Lo mejor un ejemplo: var a=1; if( a == 1 ) Game.Msg(“A es igual a 1”); Esto pregunta ¿a es igual a 1?, como le dimos ese valor, la condición se cumple y se muestra en pantalla el mensaje A es igual a 1. En el ejemplo anterior, podemos ver perfectamente como funciona las condiciones. Como puedes ver, la condición va entre paréntesis. if( aquí va la condición) acción a realizar si se cumple la condición; Veamos los operadores condicionales posible: 1.- Si quieres saber si una variable es igual a otra, o a un valor. if(variable o valor == variable o valor) acción; Ejemplo: if( a == 1) acción; 2.- Si quieres saber si una variable es distinta de otra o de un valor. if(variable o valor != variable o valor) accion; Ejemplo: if(a != 1) accion; 3.- Si quieres saber si algo es mayor que un valor. if(variable o valor > variable o valor) accion; Ejemplo: if(a > 5) accion; 4.- Si quieres saber si algo es menor que algún valor. if(variable o valor < variable o valor) accion; Ejemplo: if(5 < a) accion; 5.- Si quieres saber si algo es mayor o igual que algún valor. if(variable o valor >= variable o valor) acción; Ejemplo: if(5 >= a) acción; 6.- Si quieres saber si algo es menor o igual que algún valor. if(variable o valor <= variable o valor) acción; Ejemplo: if(5 >= a) acción; Como vimos al principio, hablamos de las variables booleanas, eran variables que solo podían tomar el valor verdadero o falso. Pues una condición no es mas que uno de estos valores. Un ejemplo: var a=5; if(a==5) acción; La condición funciona de la siguiente manera, tiene a el mismo valor que 5, como le dimos ese valor esta condición sera verdadera es decir, true, uno de los valores que se puede usar en las condiciones. Para variables booleanas(true o false), podemos hacerlo mediante un atajo: a=true; if(a) acción; //la acción se ejecuta, ya que a = true Veamos si es falsa a=false; if(a) acción; // la acción no se ejecuta, ya que a=false Pero la diversión no acaba aquí, podemos generar condiciones mucho mas complicadas, pero para entenderlo, volvamos al principio, nuestra condicion “if(a == 1)” si asignamos el valor 1 a la variable “a”, la condición podría leerse como ¿es 1 igual a 1? esta condición es verdadera y la acción es ejecutada. Si asignamos el valor 2 a la variable “a”, la condición se leería como, ¿es 2 igual a 1? en este caso, la condición es falsa y la acción no se ejecutará. Esta lógica condicional es muy habitual en la programación de ordenadores. Los programas están cargados de estas condiciones, y son fundamentales para la programación, y es necesario aprenderlo bien para usarlo correctamente. WME lee la condición y realiza una evaluación, si la condición es verdadera, se ejecuta la instrucción, y si la condición es falsa, la instrucción no se ejecuta y el programa sigue adelante. Veamos como: Volviendo a nuestro ejemplo real del botón que abre la puerta cuando es pulsado, debemos usar un script para controlar si el botón esta pulsado o no: global botonPulsado=true; Esta linea se encontrará en el script del botón, o de la escena donde este el botón. global botonPulsado; if(botonPulsado) acción que abre la puerta; Estas lineas estarán ubicadas en el script de la puerta, o de la escena donde se encuentre la puerta. Ya que hemos visto lo básico de las condiciones, podemos unir varias condiciones y evaluar mas de una misma cosa al mismo tiempo en una condición. **1.- Operador &&** Sirve para enlazar condiciones verdaderas, este operador hace la función del Y lógico, el Y lógico lo usamos cuando queremos que se cumplan varias condiciones al mismo tiempo para que se realice la acción: if( a > 1 && a < 10) acción; En esta condición podemos ver el uso del &&, la condición se leería de la siguiente manera, es “a” mayor que 1 y “a” menor que 10, si ambas condiciones se cumplen la acción es ejecutada, si alguna de las dos condiciones es falsa, la acción no es ejecutada. **2.- Operador ||** Este operador hace la función lógica O, esta la usamos cuando tenemos varias condiciones, pero con que se cumpla una de ellas, la acción es ejecutada: if( a == “jhon” || b == 10 ) acción; Esta condición se leería de la siguiente manera es “a” igual a jhon o “b” igual a 10, con que una de las dos condiciones anteriores se cumpliera, la acción se ejecutaría. Si queremos agrupar condiciones, podemos usar paréntesis para la precedencia, o para tener claridad, por ejemplo: if ( ( a > 1 && a < 10 ) || (b ==”jhon” ) ) accion; Como veis podemos crear condiciones bastantes complejas, en este caso la acción se ejecutará si “a” es mayor que 1 y “a” menor que 10 o “b” es igual a jhon, de esta manera enlazamos condiciones para asegurarnos que se cumplen los requisitos que requerimos para que una serie de instrucciones se ejecuten. Si se cumplieran las dos, es decir que “a” esta entre 1 y 10 y la “b” es igual a jhon, la acción también se ejecutaría. En este caso solo sería falsa si ambos operandos de la condición son falsos. **Un consejo:** Es posible generar condiciones muy complejas. Es cuestión de trabajarlas, y siempre preguntarse ¿que tiene que ocurrir para que pase esto? De esta manera se nos facilitará la creación de nuestras propias condiciones. Por ejemplo ¿que tiene que ocurrir para que se abra la puerta? Pues tiene que ocurrir que el botón este pulsado, pues ya sabemos que en la condición debemos introducir algo que nos diga si el botón esta pulsado o no. **Quinta regla de sintaxis** Si quieres ejecutar múltiples comandos cuando se cumple una condición, encerraremos la acciones entre llaves: if(a == 2) { Game.Msg(“hola!”); Game.Msg(“hola otra vez”); } En este caso, si la condición a == 2 se cumple, se ejecutan las dos acciones que se encuentran encerrada entre las llaves. Ahora imagina que tienes una condición que cuando se cumple se ejecuta una acción, pero imagina que también quieres que se ejecute algo cuando la condición es falsa, pues bien, en este caso usamos la palabra reservada else. Veamos un script de ejemplo: var a=1; if( a == 0) { Game.Msg(“este texto sale en pantalla si la condición es verdadera”); a = 10; } else { Game.Msg(“este texto sale en pantalla si la condición es falsa”); } Esto es una sentencia condicional(if) totalmente definida, ya que es capaz de responder a cualquier estado de la condición, si es verdadera se ejecuta el primer bloque de instrucciones, y si es falsa, se ejecuta el segundo bloque. Cuando tratemos con que la condición puede llevar varios estados, es decir si por ejemplo tenemos una variable numérica, y queremos que por ejemplo para el valor 1 haga una cosa, para el valor 2 haga otra diferente, para el valor 3 otra acción, etc pues se usa la sentencia “switch” Veamos un ejemplo con un script: var a= Random(0,3); //almacenamos en a un numero aleatorio entre 0 y 3. var b=””; //declaramos variable b con una cadena vacia. switch(a) { case 0: Game.Msg(“primera opcion”); b=”hola”; break; case 1: Game.Msg(“segunda opcion”); b=”adios”; break; default: Game.Msg(“cualquier opcion que no sea ni 1 ni 2”); b=”¿que hago?”; } Bien aquí hay muchas cosas que analizar. Lo primero es que como vemos, la variable “a” puede tomar un valor entre 0 y 3( debido a la función Random ). Si a es igual a 0, se ejecutan las tres sentencias que se encuentran tras el “case 0:” La palabra default, indica que ese bloque se ejecutará en caso de que el valor de la variable sea diferente a las de los case anteriores. La palabra reservada break sirve para decirle a wintermute que termine de evaluar el valor de “a”, ya que si no lo ponemos wme seguiría ejecutando los demás casos. Poniendo esta palabra, hacemos que cuando wme encuentra el bloque que tiene ejecutar y lo ejecute, termine, y no siga evaluando, ya que esto relentiza el programa, y ademas para que evaluarlo, si ya sabemos lo que valía la variable, y hemos ejecutado lo que nos interesa, por eso usamos la palabra reservada “break”, para finalizar la evaluación del bloque switch. Cada opción se define con la palabra reservada “case”. Se usa la palabra case y después se pone el valor que puede tomar la variable que estábamos evaluando, en nuestro caso era la “a” y se termina añadiendo dos puntos(:) case 1: accion 1; accion 2; break; En este caso cuando la variable que estamos evaluando tiene el valor 1, se ejecutan la acción 1 y la acción 2, y con break termina el flujo de la instrucción, ya que como ya tenemos lo que queríamos no hace falta seguir evaluando el switch. También es posible usar usar el switch para evaluar variables de cadenas de texto(String). case “espada”: accion1; accion2; break; **Error:** No usar bucles en los switch, no funcionan. Si lo necesitas, se hace mediante la definición de una función que contiene el bucle, pero esto lo veremos mas adelante. Solo comentarlo, no se pueden usar bucles en los switch. ===== 2.3 Bucles ===== Hay veces en las que es necesario repetir una acción o serie de acciones mas de una vez. WME proporciona varias formas de implementar esto. **Bucle for** Empezaremos con la primera forma mediante el comando for, este comando es útil si sabemos exactamente el número de repeticiones que queremos realizar, veamos como imprimir por pantalla 10 veces el mensaje infierno: for( var a=0; a < 10; a= a+1) { Game.Msg(“infierno"); } Analicemos estas lineas, el comando for se divide en 3 partes separadas por punto y coma. La primera parte “var a=0” en esta linea definimos e iniciamos la variable que se usará para recorrer el bucle, en este caso hemos definido una variable a y le hemos dado el valor 0. En la segunda parte “ a < 10 “ es la condición de fin, lo que indica es cuando terminará el bucle, en este caso le hemos puesto menor que 10, luego el bucle se ejecutara mientras a sea menor que 10. y la ultima parte “ a= a + 1” lo que indica es que la variable “a” del bucle se incrementara en 1 cada vez que ejecutan las instrucciones encerradas entre llaves, en este caso, Game.Msg(“infierno”). En esta ultima parte, la de como se modifica la variable del bucle, se puede usar cualquier operación, suma, resta, multiplicación, etc, y cualquier valor, es decir no es necesario que vaya de 1 en 1, puede ir de 2 en 2, también es posible usar atajos, con a++ “a” se incrementará en 1, y con a-- “a” se decrementará en 1. Por ejemplo: for( var a=0; a<10; a=a+2) { acciones; } De esta forma, el bucle solo se ejecutaría 5 veces, ya que la variable del bucle se va incrementando en 2 unidades cada vez que se ejecutan las acciones. for( var a=10; a == 0; a= a--) { acciones; } Como vemos en este en lugar de ir del 0 hacia arriba, vamos desde un valor hacia abajo, y cuando la variable cumpla la condición de fin es decir cuando “a” sea igual que 0, el bucle termina. Una cosa importante, es el número de veces que se ejecutará el bucle, porque dependiendo de la condición de fin y de la variación de la variable del bucle, el bucle se nos ejecutará ese número de veces. Lo mejor es trabajar con ellos para coger soltura en el numero de repeticiones que requerimos. Pero veamos algunos ejemplos útiles, ¿recordáis los arrays? Pues los bucles son geniales para recorrerlos, y no tener que ir uno a uno obteniendo los valores del array. Veamos un script de ejemplo: var miArray; miArray[0]=”hola”; miArray[1]=”¿que tal?”; miArray[2]=”Adios”; for( var a=0; a < 3;a= a + 1) { Game.Msg( miArray[a] ); } Como puedes ver es fácil imprimir por pantalla todos los elementos de un array. Espero que estéis entendiendo su uso. Trabajando con ellos veréis que es una herramienta imprescindible en programación. **Bucle while** Otro tipo de bucle es el llamado while. Este bucle es usado cuando no sabemos exactamente cuantas veces se tendrán que ejecutarse las ordenes incluidas en el bucle. Veamos un ejemplo: var a =0; while( a != 5) { a= Random(0,5); Sleep(1); } Como vemos, en el script anterior declaramos una variable a inicializada a 0, después tenemos nuestro bucle while( condición). While significa mientras, luego mientras la condición que se encierra entre paréntesis, sea verdadera, estaremos ejecutando el bucle. ¿Cuando terminará el bucle? Pues terminará cuando la función Random(0,5) que esta dentro del cuerpo del bucle asigne a nuestra variable “a” el valor 5, ya que en la condición impusimos que el bucle se ejecutara mientras “a” fuera distinto de 5. En este caso, la declaración y la definición de la variable del bucle, se realiza antes del bucle, la condición se encuentra entre paréntesis tras la palabra reservada while, y la modificación de la variable, se realiza dentro del cuerpo del bucle, así, dependiendo de lo que pase dentro del bucle, este se ejecutara un número de veces, que a priori no conocíamos. Importante: quizás te estés preguntando que es eso de sleep(1), simplemente es una función que lo que hace es desactivar el juego durante el tiempo que se le ponga entre paréntesis, en este caso 1 mili-segundo, esto es para evitar, que el bucle se coma todo el procesador y no deje paso a los demás procesos del equipo, lo que hace que todo se relentice y pueda dar problemas, es muy habitual usarlo en programación, pero hablaremos de el mas adelante. **Bucles infinitos** ejemplo: while(true) { acciones; Sleep(1); } Este es un bucle en el que la condición siempre es verdadera, por lo que siempre estará ejecutándose, es muy común usar estos bucles en procesos de fondos, por ejemplo para la musica, usas en el while una condición que compruebe si la música se esta reproduciendo o si esta parada, si esta en play no hace nada, pero si no lo esta, podremos volver a reproducir la misma, u otra canción. Para cosas como esta se usan los bucles infinitos. ===== 2.4 Funciones ===== Como ya hemos visto en el caso de Sleep() y Random(), hay una serie de herramientas llamadas funciones. Con las funciones tenemos una buena forma de ahorrar tiempo, ya que si tenemos que hacer algo varias veces a lo largo del juego, es tedioso tener que escribir el mismo código varias veces. Imagina el siguiente ejemplo: Se quiere imprimir 10 veces la palabra hola, pero quieres que esto pase varias veces seguidas, sería tedioso hacer: for(var a=0; a < 10; a=a+1) Game.Msg(“hola”); for(var a=0; a < 10; a=a+1) Game.Msg(“hola”); for(var a=0; a < 10; a=a+1) Game.Msg(“hola”); …. Para esto podríamos crear una función: function hola() { for(var a =0; a<10;a++) { Game.Msg(“hola”); } return ; } hola();//imprime 10 veces en pantalla el mensaje hola hola();//imprime 10 veces en pantalla el mensaje hola hola();//imprime 10 veces en pantalla el mensaje hola ¿Veis? esto simplifica el código. Una función es una pieza de código reutilizable, se define como sigue: function nombre_de_la_funcion(parametros) { codigo de la funcion } El fin de la función es cuando se encuentra la palabra reservada return que en ciertos casos podrá devolver algún dato que utilizaremos para controlar el programa. Pero una función como la del ejemplo anterior no tiene mucha funcionalidad, la funcionalidad se amplia cuando empezamos a hacer uso de los parámetros. Por ejemplo una modificación del ejemplo anterior con mayor funcionalidad es el siguiente: function escribeTexto(texto, contador) { for( var a=0; a< contador; a++) { Game.Msg(texto); } } escribeTexto(“hola”,10); // se muestra 10 veces hola en pantalla var b=5; escribeTexto(“ring! Ring!” , b); // se muestra 5 veces por pantalla ring! Ring! Como veis, mediante los dos parámetros texto y contador, le damos mucha funcionalidad a nuestra función, ya que cuando queramos imprimir en alguna parte del juego un texto repetidas veces en la pantalla podremos hacer uso de esta función, y no tener que hacer un bucle cada vez que queramos realizar dicho propósito. En la función escribeTexto(texto, contador), las variables texto y contador solo serán validas dentro del cuerpo de la función, por lo que solo podremos usarlos dentro de la función, y no fuera. Bueno hemos visto como pasar datos a la función para que trabaje, pero ¿como hacemos para que la función nos devuelva un valor con el que poder trabajar? Por ejemplo en la función Random(a,b) la función nos devuelve un valor comprendido entre “a” y “b”, Esto se realiza con la palabra return que indica que es lo que nos devolverá la función, veamos un ejemplo: function esMayor(number1,number2) { var mayor=false; if(number1>number2) { mayor=true; } return mayor; } esMayor(5,1);//esta funcion devuelve un true esMayor(2565,5678); //esta funcion devuelve un false Como podemos intuir,, esta función comprueba el si el number1 pasado como parámetro, es mayor que el number2, si esto es cierto, entonces cambia el valor de la variable a true, mientras que si no es cierta, el valor de la variable mayor sera false como le dimos al declararla, una vez que ha ejecutado todas las sentencias y llega a la palabra return, la función, coge el valor que tiene la variable mayor y nos lo devuelve, este valor podríamos almacenarlo en una variable, y trabajar posteriormente con el. En este caso al tratarse de un valor booleano lo que devuelve la función, podríamos por ejemplo emplearlo en condiciones directamente, veamos un ejemplo: if( esMayor(5,1) ) { Game.Msg(“el numero es mayor”); } else { Game.Msg(“el numero es menor”); } Como veis hemos metido una función que devuelve un valor booleano dentro de una condición, conforme practiquéis, aprenderéis rápidamente como usar funciones con bucles, condiciones, parámetros, arrays, etc. Llegará un momento en que aprenderéis a enlazar unas cosas con otras y crear buenos trozos de código. **Sexta regla de sintaxis** Los nombres de funciones, solo pueden contener caracteres alfanuméricos, y sin espacios entre caracteres. Ejemplos de nombres: escribirNumero() // correcta reproducirSonido5() // correcta escribir_Numero() // correcta reproducir_Sonido() // correcta escribir Numero() // incorrecta reproducir*Sonido() // incorrecta Debemos tener todo claro hasta este punto, si no es así, por favor revisa los capítulos anteriores y podrás continuar sin problemas. Si algo no queda muy claro preguntad en foro oficial y se contestará o se intentará modificar para aclararlo. ===== 2.5 Clausula include ===== Como hemos visto, las funciones ofrecen mucha potencia al programa, pero como no existe ninguna manera de declarar una función global, como hacíamos con las variables, hay de hacer que las funciones que están en un script, se puedan usar en otros scripts, para ello hay dos maneras de hacerlo, mediante la palabra reservada includes, o mediante objetos. Pero primero veamos como se usa include. Si has echado un ojo a la demo de WME abras visto que cada script comienza con la linea: #include “scripts\base.inc” Con esta linea, lo que estamos haciendo, es decir que queremos incluir este archivo de scripts en el script donde estamos trabajando, en este caso estamos incluyendo el archivo base.inc que tendrá una serie de funciones, variables, o trozos de código que podremos usar también en el script donde lo incluyamos. Por ejemplo, si no quieres declarar tus variables globales cada vez que las necesitas, puedes crear un fichero inc donde estén todas las variables globales definidas, y ya con solo incluir este fichero con la palabra include, no tenemos que andar escribiendo la declaración de las variables globales cada vez que vayamos a usarlas. También es posible hacer esto con funciones, creas un fichero inc con las funciones, y después lo incluiremos con la palabra reservada #include “ruta_y_nombre_del_archivo.inc”. Así no tendremos que copiar el código de la función en cada script donde queramos usarlo. **Nota:** fíjate que la linea #include “scripts/base.inc” no lleva punto y coma al final, y el nombre y la ruta del archivo van entre comillas. Importante: no inicialices nunca las variables en el fichero a incluir, ya que si haces eso, estas se inicializarán cada vez que hagas una llamada a un script que incluya ese fichero. ===== 2.6 Objetos ===== Veamos ahora lo que aporta la mayor funcionalidad a WME, los objetos, bien, empecemos despacio, imagina que tienes un objeto de la vida real, por ejemplo, una mesa. Pero claro el termino mesa no nos dice nada, es abstracto, ya que la mesa puede estar echa de plástico, de madera, de metal, puede tener distintos colores, puede ser cara o barata, etc tiene muchas propiedades, quizá nos convendría tener todas estas propiedades juntas para una mesa. var mesa; mesa.material=”madera”; mesa.color=”negro”; mesa.precio=100; Game.Msg(mesa.precio); //se imprimirá el precio de la mesa por pantalla. Bien, lo que hemos echo aquí, es definir una variable pero en lugar de acceder a esta variable directamente, hemos agregado una serie de atributos a la variable, ya no usamos la variable como un contenedor de un valor, sino que lo usamos para almacenar varias cosas, es muy parecido a los arrays pero en lugar de acceder por la posición, accedemos por un nombre de atributo. En el ejemplo anterior accedimos al atributo precio del objeto mesa. Game.Msg(mesa.precio); Seguro que estarás pensando esto es fantástico y maravilloso, pero si quiero crear 10 mesas, ¿necesito declarar 10 variables como esta? No, Seria muy tedioso. Bien, la magia de los objetos no solo reside en sus atributos, sino que también se pueden definir funciones para los objetos, todo el tiempo hemos estado trabajando con un objeto, Game.Msg() y ahora acabas de descubrir que este método, es un método del objeto Game. WME trabaja mucho con objetos, y conforme te adentres en su funcionamiento, más te darás cuenta de lo importantes y útiles que son. Bien, veamos como definir un objeto para algo mas de utilidad que para almacenar atributos. Bien primero crearemos un fichero donde definiremos un objeto, le llamaremos por ejemplo mesa.script #include “scripts\base.inc” method initialize(material, color, precio) { this.material=material; this.color=color; this.precio=precio; } **Septima regla de sintaxis** Si quieres acceder al atributo o funcion de un objeto, usamos un punto como hemos visto en los ejemplos anteriores. Usamos la palabra this, ya que como no sabemos a priori como le llamaremos al objeto, pues this, es una palabra reservada para referirse al objeto el cual estamos creando. Esta es la manera correcta de definir la inicialización de un objeto. Veamos ahora una vez que hemos definido el objeto mesa.script como crear un objeto de este tipo. Var mesa1 = new Object(“mesa.script”); De esta manera creamos un objeto de tipo mesa, ahora podemos definir sus propiedades llamando al método iniciar que creamos en el archivo mesa.script de la siguiente manera: mesa1.iniciar(“madera”,”negra”,100); De esta manera en nuestra mesa ya quedarán definidos sus tres atributos, pudiendo acceder a ellos con el nombre_del_objeto.nombre_del_atributo: mesa1.material: mesa1.color; mesa1.precio; Podemos ir mas allá, veamos por ejemplo como crear 10 objetos de tipo mesa usando un bucle: for( var a=0;a <10;a++) { mesas[a]= new Object(“mesa.script”); } Aquí tenemos que tener cuidado, ya que no podemos hacer mesas[a].iniciar(material,color,precio); ya que WME no soporta esto, para solucionarlo debemos hacer uso de una variable temporal, que almacene cada objeto, lo inicialice y después lo vuelva a almacenar en el array. var temp = mesas[a]; temp.iniciar(“madera”,”negra”,100); mesas[a]=temp; Con estas tres lineas, obtenemos una de las mesas del array, la iniciamos, y después la volvemos a guardar en el array, esto es necesario ya que como hemos dicho wme no soporta el acceso a los atributos o métodos de los objetos guardados en un array. Y ya solo se trata de practicar por unos mismo, y seguir con el tutorial que a partir de aquí creo que con esto no tendrás problemas para entender lo siguiente. También es posible crear mas métodos para el objeto mesa, simplemente, en el fichero mesa.script que habíamos creado, podemos añadir un método por ejemplo para cambiar el color de la mesa. Pues añadiremos en el fichero del objeto mesa el siguiente método: method cambiarColor(color) { this.color=color; } Y cuando creemos un objeto de tipo mesa, podremos cambiar el color de la mesa usando este método. var mesa = new Object("mesa.script");//creamos el objeto mesa.iniciar("metal","roja",300);// iniciamos sus valores Game.Msg(mesa.color);//se imprimirá en pantalla roja mesa.cambiarColor("azul");//cambiamos el color Game.Msg(mesa.color);//se imprimirá en pantalla azul De esta manera podemos crear métodos para los objetos. **Nota:** Método y función vienen a ser prácticamente lo mismo, con la diferencia principalmente de que las funciones tienen funcionalidad por si solas, y los métodos siempre actúan sobre algún objeto.