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.
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.
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.
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.
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.
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.
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.