Un programma
Un programma consiste di un insieme di istruzioni, statement.
Un programma deve iniziare con il simbolo { e finire con il simbolo }.
Tra questi due simboli ci sono le istruzioni.
Le istruzioni devono essere separate con un simbolo ;.
Quindi la struttura generale di ogni programma è:
{ <istruzione>; <istruzione>; ... }
C’è un certo numero di tipi diversi di istruzioni, che saranno trattati in seguito.
Variabili
Come tutti i linguaggi di programmazione GML ha le variabili.
Le variabili sono celle di memoria che mantengono informazioni.
Esse hanno un nome, in modo che si possa fare riferimento a esse.
In GML una variabile può memorizzare un numero reale oppure una stringa.
Le variabili non hanno bisogno di essere dichiarate come in molti altri linguaggi.
C’è un gran numero di variabili già presenti nel linguaggio.
Alcune sono di uso generale, come mouse_x e mouse_y che indicano la posizione attuale del mouse, mentre altre sono locali all’istanza dell’oggetto (…), come x e y che indicano la posizione attuale della istanza.
Una variabile ha un nome che deve iniziare con una lettera e può contenere soltanto lettere, numeri, e underscore, _.
La lunghezza massima è 64 simboli.
Quando utilizzi una nuova variabile questa è locale all’istanza corrente e non è visibile nei programmi delle altre istanze (anche dello stesso oggetto).
Si può, comunque, fare riferimento alle variabili di altre istanze; leggi più avanti.
Assegnazioni
Un’assegnazione memorizza un valore in una variabile.
Un’assegnazione ha la forma:
Un’espressione può essere un semplice valore ma può anche essere molto più complicata.
Invece di assegnare un valore a una variabile, si può anche aggiungere un valore al valore attuale della variabile utilizzando +=.
Allo stesso modo, puoi
- sottrarlo, -=
- moltiplicarlo, *=
- dividerlo, /=
- oppure utilizzare gli operatori sui bit, |=, &=, ^=.
Espressioni
Le espressioni possono essere
- numeri reali, come 3.4
- numeri esadecimali che iniziano con un segno $, come $00FFAA
- stringhe tra apici singoli o doppi, come ‘hello’ oppure “hello”
o espressioni più complicate.
Per le espressioni, esistono i seguenti operatori binari (in ordine di priorità):
- && || ^^ per i valori logici (and, or, xor)
- < <= == != > >= confronti, si ottiene true (1) oppure false (0)
- | & ^ operatori bit a bit (or, and, xor)
- << >> operatori di shift (shift left, shift right)
- + – addizione, sottrazione
- * / div mod moltiplicazione, divisione, divisione intera, modulo
Osserva che il valore di x div y è il valore di x/y arrotondato in direzione dello zero all’intero più vicino. L’operatore modrestituisce il resto che si ottiene dalla divisione degli operandi.
In altre parole
x mod y = x - (x div y) * y.
Inoltre, ci sono i seguenti operatori unari:
- ! not, trasforma true in false e false in true
- – nega il valore successivo
- ~ nega il valore successivo, bit a bit.
Come valori si possono usare numeri, variabili o funzioni che restituiscono un valore.
Le sottoespressioni possono essere racchiuse tra parentesi tonde.
Tutti gli operatori funzionano con valori reali.
I confronti funzionano anche con stringhe e + concatena le stringhe.
Attenzione, al contrario di certi linguaggi, entrambi gli argomenti di un operatore logico sono sempre valutati, anche quando il primo argomento determina in anticipo il risultato.
Esempio
Ecco un esempio con delle assegnazioni
{ x = 23; color = $FFAA00; str = 'hello world'; y += 5; x *= y; x = y << 2; x = 23*((2+4) / sin(y)); str = 'hello' + " world"; b = (x < 5) && !(x==2 || x==4); }
Variabili aggiuntive
Si creano nuove variabili assegnando loro un valore (non è necessario dichiararle prima!).
Semplicemente se usi il nome di una variabile, la variabile sarà memorizzata insieme all’istanza dell’oggetto attuale.
Quindi non ti aspettare di ritrovarla quando dopo utilizzi un altro oggetto (o un’altra istanza dello stesso oggetto).
Puoi assegnare e leggere variabili in altri oggetti accompagnandole con il nome dell’oggetto e un punto prima del nome della variabile.
Per creare variabili globali, cioè visibili alle istanze di tutti gli oggetti, aggiungi all’inizio la parola global e un punto.
Per esempio si scrive:
{ if (global.ok) { // succede qualcosa... global.ok = false; } }
In alternativa si possono dichiarare le variabili come globali.
Questa dichiarazione sarà simile alla seguente
globalvar <varname1>,<varname2>,<varname3>, ... ;
Dopo che la dichiarazione è stata eseguita, la variabile sarà trattata sempre come globale senza il bisogno di aggiungere davantiglobal..
Necessita soltanto di essere dichiarata una volta in una pezzo di codice che viene eseguito.
Dopo, in qualunque altro posto la variabile viene trattata come globale.
A volte vuoi variabili soltanto all’interno del codice o script attuale.
In questo modo non sprechi memoria e sei sicuro che non ci siano conflitti tra i nomi.
È anche più veloce dell’uso di variabili globali.
Per questo devi dichiarare le variabili all’inizio della porzione di codice utilizzando la parola chiave var.
Questo tipo di dichiarazione somiglia alla seguente
Per esempio, scrivi
{ var xx, yy; xx = x+10; yy = y+10; crea_istanza(xx, yy, ball); }
Far riferimento a variabili di altre istanze
Come detto prima, si assegna un valore a una variabile della stessa istanza utilizzando un costrutto come
x = 3;
Ma in certi casi vuoi far riferimento a variabili in altre istanze.
Per esempio, potresti voler fermare il movimento di tutte le palle, oppure muovere il personaggio principale in una certa posizione, oppure, in caso di collisione, impostare la sprite delle altre istanze coinvolte.
Puoi ottenerlo precedendo il nome della variabile con il nome di un oggetto e un punto.
Per esempio, puoi scrivere
ball.speed = 0;
In questo modo cambierà la velocità di tutte le istanze dell’oggetto palla.
C’è un certo numero di oggetti speciali.
- self: L’istanza attuale per la quale si sta eseguendo l’azione
- other: L’altra istanza coinvolta in un evento di collisione
- all: Tutte le istanze
- noone: Nessuna istanza (probabilmente suonerà strano ma ritornerà utile come vedremo in seguito)
- global: Non è un’istanza, ma un contenitore per le variabili globali
Allora, per esempio, puoi utilizzare i seguenti tipi di istruzione:
other.sprite_index = sprite5; all.speed = 0; global.messaggio = 'A good result'; global.x = palla.x;
Adesso potresti stupirti per per quello che fa l’ultima assegnazione nel caso ci siano più palle.
Bene, prende la prima e assegna il suo valore x alla variabile globale.
Ma se vuoi impostare la velocità di una particolare palla piuttosto che di tutte?
- Questo è leggermente più difficile.
Quando inserisci le istanze nel livello, l’id dell’istanza è visibile se passi il mouse sull’istanza.
Si tratta di numeri >= 100.000.
- Questo numero puoi utilizzarlo anche a sinistra del punto.
Per evitarlo racchiudilo tra parentesi.
Per esempio, supponiamo che l’id della palla sia 100032, allora puoi scrivere:
(100032).speed = 0;
- Quando crei un’istanza nel programma, la chiamata restituisce l’id.
- Allora una porzione di codice valida è la seguente:
{ nnn = instance_create(100, 100, ball); nnn.speed = 8; }
- Osserva che abbiamo assegnato l’id dell’istanza a una variabile e poi abbiamo utilizzato questa variabile insieme con il punto.
Cerchiamo di essere più precisi.
Un punto è a tutti gli effetti un operatore.
Dati i due argomenti, a sinistra e a destra, restituisce l’indirizzo di una variabile all’interno di un oggetto o istanza.
Tutti i nomi degli oggetti e gli oggetti speciali rappresentano dei valori e possono essere trattati come qualsiasi altro valore.
Per esempio, il prossimo codice è valido:
{ obj[0] = ball; obj[1] = flag; obj[0].alarm[4] = 12; obj[1].id.x = 12; }
L’ultima istruzione dovrebbe essere letta come segue.
Prendiamo l’id del primo flag.
Impostiamo a 12 la coordinata x dell’istanza con questo id.
- I nomi degli oggetti, gli oggetti speciali gli id delle istanze possono essere inoltre utilizzati in un certo numero di funzioni.
Array
In GML puoi utilizzare array monodimensionali e bidimensionali.
Semplicemente metti l’indice tra le parentesi quadre per gli array monodimensionali, e i due indici separati da una virgola per gli array bidimensionali.
Nel momento in cui utilizzi un indice viene generato l’array.
Ciascun array inizia con l’indice 0.
Presta attenzione all’uso di indici grandi perché sarà riservata memoria per un array grande…
Non utilizzare mai indici negativi.
Il sistema pone un limite di 32000 per ciascun indice e di 1.000.000 per la dimensione totale.
Quindi puoi scrivere per esempio come segue:
{ a[0] = 1; i = 1; while (i < 10) { a[i] = 2*a[i-1]; i += 1; } b[4, 6] = 32; }