if (global.hacer)
{
// hacer cualquier cosa
global.hacer = false;
}
}
A veces quieres variables que solo estén dentro del actual piece of code o de un script. De esta manera evitas perder memoria y estás seguro que no hay ningún conflicto con los nombres. Esto es también más rápido que usar variables globales. Para hacer esto debes declarar las variables en el comienzo del código, usando la palabra “var”. Esta declaración se ve así:
var <nombrevariable1>,<nombrevariable2>,<nombrevariable3>, ...
Por ejemplo, puedes escribir:
{
var xx,yy;
xx = x+10;
yy = y+10;
instance_create(xx,yy,pelota);
ACCEDIENDO A VARIABLES EN OTRAS INSTANCIAS
Como se dijo antes, puedes alterar variables en la instancia actual usando sentencias como:
Pero en ciertos casos querrás acceder a variables en otra instancia. Por ejemplo, para detener el movimiento de todas las pelotas, o para mover al personaje principal a cierta posición, o, en el caso de una colisión, cambiar el sprite de la otra instancia involucrada. Esto puede lograrse antecediendo el nombre del objeto y un punto al nombre de la variable. Así por ejemplo, puedes escribir:
Esto cambiará la velocidad de todas las instancias del objeto pelota. Hay ciertos “objetos” especiales.
- self: La instancia actual para la que estamos ejecutando la acción
- other: La otra instancia involucrada en un evento de colisión
- all: Todas las instancias
- noone: Ninguna instancia (tal vez te parezca raro pero puede ser útil como veremos más adelante)
- global: : No es precisamente una instancia, sino un contenedor que almacena variables globales
Por ejemplo, puedes usar las siguientes sentencias:
other.sprite_index = sprite5;
all.speed = 0;
global.message = 'Un buen resultado';
global.x = pelota.x;
Ahora tal vez te estés preguntando lo que la última tarea realiza cuando hay más de una pelota. Bien, se toma la primera y su valor x es asignado al valor global.
Pero qué tal si deseas establecer la velocidad de una pelota en particular, en lugar de la de todas ellas. Esto es un poco más difícil. Cada instancia tiene un id único. Cuando colocas instancias en un cuarto en el diseñador, este id se muestra cuando colocas el ratón sobre la instancia. Estos números son mayores o iguales a 100000. Puedes emplear estos números como la parte a la izquierda del punto. Pero ten cuidado, el punto será interpretado como el punto decimal en el número. Para evitarlo, colócalo entre paréntesis. Así por ejemplo, asumiendo que el id de la pelota es 100032, puedes escribir:
Cuando creas una instancia en el programa, la llamada devuelve su id. Una pieza de programa válido es:
{
nnn = instance_create(100,100,pelota);
nnn.speed = 8;
}
Esto crea una pelota y establece su velocidad. Nota que hemos asignado el id de la instancia a una variable y usamos esta variable como indicación antes del punto. Esto es completamente válido. Déjame explicarlo un poco mejor. Un punto es de hecho, un operador. Toma un valor como el operador de la izquierda y una variable (dirección) como el operador de la derecha, y devuelve la dirección de esta variable en particular para el objeto o instancia indicados. Todos los nombres de objetos, y los objetos especiales nombrados antes representan valores y pueden ser tratados como con cualquier otro valor. Por ejemplo, el siguiente programa es válido:
{
obj[0] = pelota;
obj[1] = bandera;
obj[0].alarm[4] = 12;
obj[1].id.x = 12;
}
La última sentencia debiera interpretarse como sigue. Tomamos el id de la primera bandera. Para la instancia con ese id establecemos a 12 su coordenada x.
Los nombres de objetos, objetos especiales y los id de las instancias pueden también emplearse en otros programas.
ARRAYS
Puedes emplear arrays de una o dos dimensiones en el GML. Simplemente coloca el índice entre corchetes cuadrados para un array unidimensional, y los dos índices con una coma entre ellos para los arrays bidimensionales. En el momento en que emplees un índice el array es generado. Cada array inicia en el índice 0. Por lo que debes tener cuidado al usar índices muy grandes ya que se ocupará memoria para un array grande. Nunca emplees índices negativos. El sistema coloca un límite de 32000 para cada índice y 1000000 para el tamaño total. Por ejemplo, puedes escribir lo siguiente:
{
a[0] = 1;
i = 1;
while (i < 10) { a[i] = 2*a[i-1]; i += 1;}
b[4,6] = 32;
SENTENCIA IF
Una sentencia If tiene esta forma
if (<expresión>) <sentencia >
o
if (<expresión>) <sentencia> else <sentencia >
La sentencia también puede ser un bloque. La expresión se evaluará. Si el valor (redondeado) es <=0 (false) se ejecuta la sentencia después del else, de otra forma (true) se ejecuta la otra sentencia. Es un buen hábito colocar siempre corchetes a las sentencias en la sentencia if. Por lo que mejor usa
if (<expresión>)
{
<Sentencia >
}
else
{
<Sentencia >
}
Ejemplo
El siguiente programa mueve el objeto hacia el medio de la pantalla.
{
if (x<200) {x += 4} else {x -= 4};
SENTENCIA REPEAT
Una sentencia repeat tiene esta forma
repeat (<expresión>) <sentencia >
La sentencia es repetida el numero de veces indicado por el valor redondeado de la expresión.
Ejemplo
El siguiente programa crea 5 pelotas en posiciones aleatorias.
{
repeat (5) instance_create(random(400),random(400),pelota);
SENTENCIA WHILE
Una sentencia While tiene esta forma
while (<expresión>) <sentencia>
Mientras la expresión sea verdadera, la sentencia (que puede también ser un bloque) es ejecutada. Ten cuidado con tus ciclos while. Puedes fácilmente hacer que se repitan eternamente, en cuyo caso el juego se bloqueará y ya no responderá a los comandos del usuario.
Ejemplo
El siguiente programa trata de colocar el objeto actual en una posición libre (esto es casi lo mismo que la acción para mover un objeto a una posición aleatoria).
{
while (!place_free(x,y))
{
x = random(room_width);
y = random(room_height);
}
SENTENCIA DO
La sentencia Do tiene esta forma:
do <sentencia> until(<expresión>)
La sentencia (que puede también ser un bloque) es ejecutada hasta que la expresión sea verdadera. La sentencia se ejecuta por lo menos una vez. Ten cuidado con los ciclos do. Puedes fácilmente crear uno que se repita indefinidamente, en cuyo caso el juego se bloqueará y ya no responderá a los eventos generados por el usuario.
Ejemplo
El siguiente programa intenta colocar el objeto actual en una posición libre (esto es lo mismo que mover un objeto en una posición aleatoria)
{
do
{
x = random(room_width);
y = random(room_height);
}
until (place_free(x,y))
SENTENCIA FOR
Una sentencia For tiene esta forma:
for (<sentencia1> ; <expresión> ;<sentencia2>) <sentencia3>
Funciona de la manera siguiente. Primero se ejecuta la sentencia1. Entonces se evalúa la expresión. Si es verdadera, se ejecuta la sentencia3; entonces la sentencia2 y luego se evalúa nuevamente la expresión. Esto continúa hasta que la expresión sea falsa.
Puede sonar complicado. Debes interpretarlo de la manera siguiente. La primera sentencia inicializa el ciclo for. La expresión prueba si el ciclo debiera terminar. La
sentencia2 es la sentencia de paso hacia la evaluación del siguiente ciclo.
El uso más común es para llevar un contador hasta cierto valor.
Ejemplo
El siguiente programa inicializa un array llamada “lista” de longitud 10 con los valores 1-10.
{
for (i=0; i<=9; i+=1) lista[i] = i+1;
SENTENCIA SWITCH
En ciertas situaciones querrás llevar a cabo alguna acción dependiendo de un valor en particular. Puedes lograrlo empleando varias sentencias if pero es más sencillo si empleas la sentencia switch. Una sentencia switch tiene la siguiente forma:
switch (<expresión>)
{
case <expresión1>: <statement1>; ... ; break;
case <expresión2>: <statement2>; ... ; break;
...
default: <statement>; ...
}
Funciona así: primero se ejecuta la expresión. Después se compara con los resultados de las diferentes expresiones delante de las sentencias case. La ejecución continúa después de la sentencia case con el valor correcto, hasta que se encuentre una sentencia break. Si no se encuentra una sentencia case con el valor correcto, la ejecución continúa después de la sentencia default. (No es necesaria la sentencia default. Nota que se pueden colocar múltiples sentencias case para la misma sentencia. También, no es necesaria la sentencia break. Si no existe una sentencia break, la ejecución simplemente continúa con el código para la siguiente sentencia case.
Ejemplo
El siguiente programa lleva a cabo una acción según la tecla que se presione.
switch (keyboard_key)
{
case vk_left:
case vk_numpad4:
x -= 4; break;
case vk_right:
case vk_numpad6:
x += 4; break;
SENTENCIA BREAK
La sentencia Break tiene esta forma:
Si se emplea en un ciclo for, while, repeat, en una sentencia switch o with, finaliza el ciclo o sentencia. Si es empleada fuera de una de estas sentencias finaliza el programa no el juego).
SENTENCIA CONTINUE
La sentencia Continue tiene esta forma
Si se emplea dentro de un ciclo for, while, repeat o con una sentencia with, continua con el siguiente valor del ciclo for o de la sentencia with.
SENTENCIA EXIT
La sentencia Exit tiene esta forma:
Simplemente termina la ejecución del programa/script actual. (¡No termina la ejecución del juego! Para ello necesitas la función game_end(); ver más abajo)
FUNCIONES
Una función tiene la siguiente estructura: nombre de la función, seguido por uno o varios argumentos entre paréntesis, separados por comas (también puede no incluir ningún argumento).
<función>(<arg1>,<arg2>,...)
Hay dos tipos de funciones. En primer lugar, tenemos una gran cantidad de funciones internas, para controlar todos los aspectos del juego. Después, cualquier scipt que definas en el juego puede ser usado como una función.
Nota que para una función sin argumentos aún se necesitan los paréntesis. Algunas funciones devuelven valores y pueden ser empleadas en expresiones. Otras simplemente ejecutan órdenes.
Nota que es imposible usar una función como el lado izquierda de una asignación. Por ejemplo, no puedes escribir instante_nearest(x,y,obj).speed = 0. En lugar, debes escribir(instance_nearest(x,y,obj)).speed = 0.
SCRIPTS
Cuando creas un script, querrás tener acceso a los argumentos enviados a él (ya sea cuando uses una acción script, o cuando llames al script como una función desde un programa u otro, o inclusive desde el mismo script). Estos argumentos se almacenan en las variables argument0, argument1, …, argument15. Por lo que puede haber como máximo 16 argumentos. (Nota: cuando se llama un script desde una acción, sólo se pueden especificar los primeros 5 argumentos). Pueden usar también argument[0], etc.
Los scripts también pueden devolver un valor, por lo que pueden ser empleados en expresiones. Para ello debes emplear la sentencia return:
¡La ejecución del script termina en la sentencia return!
Ejemplo
Aquí esta la definición de un script que calcula el cuadrado del argumento:
{
return (argument0*argument0);
}
Para llamar un script desde una pieza de código, solo hazlo como cuando se hacen las llamadas a funciones. Esto es, escribe el nombre del script con sus argumentos entre paréntesis.
CONSTRUCCIONES WITH
Como se indicó antes, es posible leer y cambiar el valor de las variables en otras instancias. Pero en ciertos casos querrás hacer mucho más con esas otras instancias. Por ejemplo, imagina que deseas mover todas las pelotas 8 píxeles hacia abajo. Pudieras pensar que eso se logra con el siguiente código
Pero no es correcto. El valor a la derecha de la asignación obtiene la coordenada y de la primera pelota y le suma 8. Entonces este nuevo valor se toma como la coordenada y para todas las pelotas. Por lo que el resultado es que todas las pelotas tienen la misma coordenada y. La sentencia
tendrá exactamente el mismo efecto porque es simplemente una abreviatura de la primera declaración. Entonces, ¿cómo logramos esto? Para ello existe la declaración with. Su forma general es
with (<expresión>) <sentencia>
<expresión> indica una o más instancias. Para esto puedes emplear el id de la instancia, o el nombre de un objeto (para indicar todas las instancias de este objeto) o uno de los objetos especiales (all, self, other, noone). <declaración> se ejecuta para cada una de las instancias indicadas, como si la instancia fuera la instancia (self) actual. Así, para mover todas las pelotas 8 píxeles hacia abajo, puedes escribir
Si deseas ejecutar múltiples declaraciones, colócalas entre corchetes. Por ejemplo, para mover todas las pelotas a una posición aleatoria, puedes usar
with (pelota)
{
x = random(room_width);
y = random(room_height);
}
Nota que, dentro de las sentencias, la instancia indicada se ha vuelto la instancia self. Entonces, la instancia self original ahora es la instancia other. Así, por ejemplo, para mover todas las pelotas a la posición de la instancia actual, puedes usar
with (pelota)
{
x = other.x;
y = other.y;
}
El uso de la declaración with es muy poderoso. A continuación te muestro unos cuantos ejemplos más. Para destruir todas las pelotas usas
with (pelota) instance_destroy();
Si una bomba explota y tu quieres destruir todas las instancias cercanas a ella puedes usar
with (all)
{
if (distance_to_object(other) < 50) instance_destroy();
FUNCIONES Y VARIABLES EN GML
El GML contiene un gran número de funciones y variables internas. Con ellas puedes controlar cualquier parte del juego. Para todas las acciones existe una función correspondiente por lo que de hecho no necesitas emplear ninguna acción si prefieres emplear código. Pero hay muchas más funciones y variables que controlan aspectos del juego que no se pueden acceder sólo empleando acciones. Por lo que si deseas crear juegos más avanzados se te recomienda leer los siguientes capítulos para tener un panorama general de todo lo que es posible lograr. Por favor nota que estas variables y funciones pueden también emplearse cuando se envían valores para las acciones. Por lo que aún si no planeas emplear código o escribir algún script, aún obtendrás beneficios de esta información.
En los capítulos siguientes se emplean las siguientes convenciones. Los nombres de variables marcados con un * son sólo de lectura, es decir, no se puede cambiar su valor.
Los nombres de variables con [0...n] después de ellos son arrays. Se da el intervalo posible de sus índices.
COMENTARIOS
Puedes agregar comentarios a tus programas. Todo en una línea después de // no se ejecuta. Puedes hacer también una multi-línea de comentarios colocando el texto entre /* y */.
EXPRESIONES