La struttura di base di un programma dinamico scritto in Processing è questa:
void setup()
{
}
void draw()
{
}
La funzione setup viene eseguita una sola volta quando si avvia il programma e quindi è indicata per tutte le istruzioni di inizializzazione o che devono essere eseguite una sola volta.
La funzione draw, invece, viene eseguita 30 volte al secondo (in realtà la frequenza è variabile ma è determinata automaticamente dal programma) ed è indicata per le istruzioni di sintesi dinamica dello sketch.
Proviamo, ad esempio, a far girare questo codice:
void setup()
{
size(800,600);
background(255);
fill(255,0,0);
ellipse(200,300,100,100);
}
void draw()
{
}
Qual è la funzione di tutte le istruzioni utilizzate e qual è il ruolo dei parametri all'interno delle istruzioni? Proviamo a modificarli e a verificare l'esito.
Com'è organizzato il canvas (ovvero il piano di disegno) di Processing? Dove si trova l'origine e come sono orientati gli assi?
______
Ora proviamo a spostare le due istruzioni di disegno dalla funzione setup alla funzione draw.
void setup()
{
size(800,600);
background(255);
}
void draw()
{
fill(255,0,0);
ellipse(200,300,100,100);
}
Cosa succede? Perché?
In effetti stiamo soltanto disegnando 30 volte al secondo lo stesso cerchio nello stesso punto del canvas e con le stesse caratteristiche. Per introdurre una variazione percepibile dobbiamo introdurre una grandezza che si modifichi ad ogni iterazione (cioè passaggio nella funzione draw). Proviamo a farlo attraverso l'uso di una variabile.
Una variabile è una posizione della memoria del computer alla quale possiamo assegnare liberamente un nome e modificarne il valore attraverso un'operazione di assegnazione (definita dal simbolo = che non significa uguale in senso matematico). Una variabile può contenere solo un tipo di dato come, ad esempio, un numero intero (int) oppure un numero con la virgola (float) o ancora un carattere (char). Nei linguaggi come Processing è obbligatorio specificare il tipo di dato della variabile quando questa viene dichiarata.
int i = 0; // dichiaro la variabile i di tipo intero e le assegno il
// valore 0
void setup()
{
size(800,600); // inizializzo il canvas
background(255); // scelgo il colore dello sfondo
}
void draw()
{
fill(255,0,0);
ellipse(200,300,100 + i,100 + i);
i = i + 1;
}
Ora proviamo ad usare la variabile i insieme ad altri parametri, per esempio nell'ascissa della posizione del cerchio.
Cosa succede? Perché?
NB1: Le variabili sono utilizzabili dal programma a seconda della posizione in cui vengono dichiarate. Quelle dichiarate all'inizio del programma sono visibili da tutte le funzioni. Si chiamano variabili globali. Se avessi dichiarato la variabile i nella funzione setup, non l'avrei potuta usare nella funzione draw...
NB2: tutte le righe di testo che cominciano con il doppio slash "//" sono commenti ovvero la possibilità di scrivere liberamente testo che non viene interpretato come istruzioni e quindi eseguito, ma può essere utile per annotazioni, spiegazioni e documentazione.
______
Il nostro prossimo obiettivo è realizzare un cerchio che attraversa il canvas con un moto rettilineo uniforme. Come si trasformano le equazioni del moto tempo-continuo in un mondo in cui il tempo è discretizzato e procede a salti?
Ecco una possibile implementazione.
// dichiarazione delle variabili
float posx, posy; // due componenti per la posizione
float vx, vy; // due componenti per la velocità
float t, dt; // il tempo e l'incremento di tempo
void setup()
{
size(800, 600);
t = 0; // il contatore del tempo comincia da zero
dt = 1; // il delta-t viene inizializzato ad 1
posx = 100; // x e y della posizione iniziale
posy = 200;
vx = 1; // componenti x e y del vettore velocità
vy = 0.5;
}
void draw()
{
background(255);
fill(255, 0, 0);
ellipse(posx, posy, 10, 10); // disegno l'ellisse
textSize(15);
text("t: " + t, 10, 25); // visualizzo il valore del tempo
posx = posx + vx * dt; // applico le equazioni del moto r.u.
posy = posy + vy * dt; // alla posizione
t = t + dt; // incremento il tempo
// si può scrivere anche t += dt;
}
Le ultime tre istruzioni realizzano le equazioni del moto rettilineo uniforme in un universo tempo-discreto in cui il tempo procede a salti di ampiezza dt. Da notare che, data la struttura dell'istruzione di assegnazione, scrivere
posx = posx + vx * dt;
vuol dire in sostanza che la variabile posx all'istante attuale si ottiene dal valore di posx all'istante precedente (quello a destra dell'uguale) sommandogli il prodotto di vx per dt.
Variando i valori di vx e vy si ottengono tutte le direzioni di movimento nel piano cartesiano.