SlideShare a Scribd company logo
1 of 69
Download to read offline
processing guida introduttiva alla programmazione visuale
1
processing
guida introduttiva alla programmazione visuale
alberto cecchi valerio belloni ...
indice:
prima parte:
seconda parte:
terza parte:
quarta parte:
quinta parte:
This work is licensed under the Creative Commons Attribution-
Noncommercial-Share Alike 3.0 Unported License. To view a copy
of this license, visit http://creativecommons.org/licenses/by-nc-
sa/3.0/ or send a letter to Creative Commons, 171 Second Street,
Suite 300, San Francisco, California, 94105, USA.
processing guida introduttiva alla programmazione visuale
2
p.3
p.34
p.48
p.54
p.60
Processing
Programmare per l’arte
Prima Parte
Possiamo dire che Processing è un software grafico che si occupa di
Immagini, Forme, Movimenti, Suoni e Interazioni.
Processing è allo stesso tempo un linguaggio di programmazione, un
ambiente di sviluppo nonché un metodo di insegnamento della
programmazione.
Processing è stato inventato da Casey Reas e Ben Fry al fine di
insegnare agli studenti nel settore dell’arte e della grafica la
programmazione software.
Oggi Processing è utilizzato da studenti, artisti, designers e
ricercatori per imparare, sperimentare e produrre. Processing
rappresenta in pieno il proverbio di Confucio:
“se ascolto dimentico, se vedo ricordo, se faccio capisco”
Processing, in quanto linguaggio di programmazione, è un
linguaggio testuale (si scrivono le istruzioni) pensato per produrre e
modificare immagini. Processing è il giusto compromesso tra
semplicità (nell’uso) e complessita dei risultati che si possono
raggiungere. Sono sufficienti pochi minuti di corso affinchè uno
studente possa scrivere le prime righe di codice ed osservare dei
risultati.
Utenti avanzati possono invece realizzare progetti anche molto
complessi scrivendo direttamente delle librerie che possono anche
migliorare ed aumentare le funzionalità del software stesso.
I lavori fatti in Processing possono essere facilmente esportati nel
web e questo aspetto ha facilitato la distribuzione del software e
della sua conoscenza. Il sito ufficiale di Processing è
www.processing.org, all’interno del sito è presente anche un forum
con migliaia di iscritti che discutono assiduamente riguardo le
problematiche tecniche e creative.
Processing facilita l’insegnamento della grafica digitale, delle tecniche
di interazione come ad esempio disegno vettoriale e raster, image
processing guida introduttiva alla programmazione visuale
3
processing, gestione degli eventi del mouse e della tastiera e
comunicazione nelle reti di computer.
Le librerie estendono le funzionalità di base anche alla generazione
dei suoni, alla comunicazione dei dati (input/output) alle
funzionalità tridimensionali ed esportazioni file in vari formati.
Il linguaggio Processing non è molto diverso da tanti altri linguaggi
di programmazione. Processing è stato progettato raffinando e
rivedendo questi linguaggi che lo hanno preceduto. Questo aspetto è
molto importante, infatti possiamo vedere Processing come uno
strumento per avvicinarsi alla programmazione. Chi impara a
programmare in Processing avrà il futuro molto facilitato qualora
volesse imparare a programmare anche in altri linguaggi.
L’aspetto principale che differenzia Processing da altri linguaggi di
programmazione riguarda la sua versatilità per tutto ciò che è legato
alla grafica, al disegno, all’animazione e alle interazioni live.
Installare e Aprire Processing
Processing è appunto Open Source e completamente gratuito. Per
Scaricarlo è sufficiente andare all’indirizzo www.processing.org/
download dove si trovano le versioni per Linux, OSX e Windows.
L’ambiente di sviluppo di Processing (Processing Development
Environment PDE) è composto da un semplice editor testuale dove
vengono scritte le istruzioni. PDE è anche l’estensione dei file di
lavoro prodotti in Processing.
Poi troviamo un’area messaggi, una console testuale e una toolbar
dalla quale possono essere effettuate le operazioni più comuni
(nuovo, apri, salva, esporta…). Sempre nella Toolbar in alto sono
presenti i due tipici pulsanti degli ambienti di programmazione (Stop
e Run).
Ecco la lista completa dei pulsanti presenti nella Toolbar:
RUN
STOP
NEW
OPEN
SAVE
EXPORT
processing guida introduttiva alla programmazione visuale
4
Quando si lancia un programma (Run) il risultato compare in una
finestra che si apre automaticamente (display window).
Ogni programma scritto con Processing (attraverso l’editor testuale)
si chiama Sketch. All’interno dell’editor testuale sono presenti le due
tipiche funzionalità Taglia e Incolla (Cut and Paste) e Cerca e
Sostituisci (Search and Replace).
L’area messaggi, in basso ci dice ad esempio se una volta lanciato il
programma ci sono errori. In pratica l’area messaggi è il mezzo che
Processing usa per comunicare con noi, scrivendoci in quell’area
qualunque tipo di messaggio riguardo il suo comportamento (ad
esempio se si scrive uno Sketch errato sarà l’area messaggi ad
avvertirci).
L’area della conosole testuale (sotto l’area messaggi) ci scrive dei
messaggi in forma più estesa e dettagliata della message window).
Questa area ha anche la funzione di controllo durante le operazioni
di programmazione. Ad esempio quando si vuole controllare una
fare intermedia della programmazione, possiamo far comparire in
questa finestra i dati desiderati (più avanti sarà tutto più chiaro).
I menu di Processing sono solo 6:
Processing
File
Edit
Sketch
Tools
Help
Questa breve lista dei menù all’interno dei quali troviamo pochi
comandi, rende l’idea della semplicità dell’ambiente di sviluppo
Processing. Vedremo i comandi all’interno dei menù più avanti.
Quando si crea un nuovo Sketch (programma) Processing crea
automaticamente anche una specifica cartella che avrà lo stesso
nome dello sketch (come spiegato prima il file dove è scritto il
programma ha l’estensione .pde).
Processing è un ambiente in grado di gestire file multimediali
pertanto se all’interno del nostro progetto per esempio aggiungiamo
un suono o un’immagine questi file andranno a collocarsi
automaticamente dentro la cartella data, all’interno della cartella
dello Sketch. Processing permette di lavorare secondo la logica
“drag and drop” pertanto per aggiungere un’immagine al nostro
programma è sufficiente prendere il file e trascinarlo sopra l’editor
testuale dove stiamo scrivendo il nostro Sketch.
processing guida introduttiva alla programmazione visuale
5
La cartella dello Sketch che a sua volta conterrà anche la cartella data
con tutti i file multimediali aggiunti si troverà in una directory del
computer che possiamo decidere dal menù File/Preferences.
Programmare in Processing
Abbiamo detto che programmare in Processing è molto semplice
pertanto il modo migliore per capire questo concetto è iniziare a
scrivere qualche semplice programma cercando di comprenderne il
senso.
//Creiamo una finestra 320 x 240 pixel//
size(320, 240);
background(255);
Abbiamo scritto tre righe nella finestra testuale dell’ambiente di
sviluppo di Processing.
La prima riga potrebbe sembrare semplice e tutti i programmatori
giovani o inesperti o egoisti o masochisti tendono a trascurare
questo tipo di istruzione che invece è determinante.
Ogni volta che scriviamo un programma dobbiamo aggiungere dei
commenti che possano essere letti dai programmatori ma che non
vengano interpretati come istruzioni dal programma stesso. I
commenti sono importanti perchè attraverso i commenti il
programmatore dichiara le operazioni che compie in modo che
potrà rileggerli in futuro oppure in modo che altri programmatori
che apriranno il programma leggendo i commenti possano capire
come ha ragionato il programmatore precedente.
Commentare un programma significa comunicare con se stessi (nel
futuro) e con gli altri. Non commentare un programma significa non
comunicare ne con se stessi (quando un anno dopo aprirete un
programma fatto e non commentato non ricorderete quali
ragionaventi avrete fatto e vi dispererete) ne con altre persone alle
quali per lavoro o per divertimento volete lasciare in eredità il vostro
lavoro. Un programma non commentato è spazzatura.
Questo aspetto così centrale della programmazione risulta ancor più
centrale quando ci riferiamo ad un programma Open Source come
Processing. Processing non costa nulla perchè delle persone buone
d’animo hanno lavorato a lungo e hanno deciso di larsciarci in
eredità gratuita il loro lavoro. Un programmatore che non scrive i
commenti sui programmi realizzati in processing contravviene alla
processing guida introduttiva alla programmazione visuale
6
filosofia Open Source perchè i suoi programmi saranno
difficilmente interpretabili da altri programmatori.
La stesso giudizio però vale anche per i programmatori che lavorano
in ambiti commerciali. Un programmatore che non commenta i
propri software danneggia economicamente il suo datore di lavoro e
tutto l’ambiente nel quale lavora.
Torniamo quindi alla nostra prima riga di programma scritta in
Processing
//Creiamo una finestra 320 x 240 pixel//
I due slash “//” indicano esattamente l’inizio e la fine di un
commento del programmatore. Questo commento è molto semplice
agli occhi di un programmatore esperto potrebbe sempbrare inutile
ma in realtà quanto più diffusamnte è documentato un software
tanto più facile sarà la sua lettura e correzione in futuro.
Per scrivere dei commenti che siano più lunghi di una riga
Processing ci permette di utilizzare anche la seguente forma:
/* I commenti sono molto importanti
possiamo scriverli anche in più righe
il software non interpreta queste istruzioni
*/
Vediamo invece ora la prima istruzione (o funzione) vera e propria:
size(320, 240);
Possiamo notare in questa istruzione tre elementi importanti:
- Il comando “size”
- I parametri (320, 240)
- Il simbolo che chiude l’istruzione “;”
Il comando “size” stabilisce che deve essere creata una finestra.
Questa è la tipica istruzione con cui si inizia a programmare in
Processing. Con “size” si stabiliscono le dimensioni della finestra
sulla quale poi compariranno i risultati del nostro programma.
Le dimensioni che abbiamo stabilito in questo caso sono 320 pixel
in larghezza (asse X) e 240 pixel in altezza (asse Y).
Con “;” invece diciamo a Processing è terminata l’istruzione.
Da notare la seguente istruzione:
processing guida introduttiva alla programmazione visuale
7
//size(320, 240);
Poichè la riga inizia con “//” Processing interpreterà tutto ciò che
segue come un commento e quindi quando si lancerà il programma
non verrà effettuata nessuna azione. A volte i programmatori
disordinati tendono a commentare molto le istruzioni durante il
processo produttivo. Questa operazione se non documentata è un
operazione che genera solo confusione. Pertanto quando si
commenta un’istruzione è bene spiegare, attraverso un ulteriore
commento il motivo per il quale sono presenti delle istruzioni
commentate.
Rispetto ai paramentri è importante notare che ad esempio nel caso
di “size” debbono essere 2 e la loro posizione è obbligatoria. Al
primo posto si mette il valore delle X e al secondo posto (dopo la
virgola) si mette il valore delle Y.
Infine da notare un aspetto molto importante della
programmazione, la convenzione di chiudere l’istruzione con “;”
potrebbe sembrare inutile e noiosa. Potrebbe anche essere così, ma
comunque è dobbiamo capire che qualora non mettessimo quel
dettaglio “;” il nostro programma non funzionerà. I linguaggi di
programmazione usano una sintassi molto più rigida della sintassi
che si usa quando si parla o quando si scrive una mail. Quando
scriviamo una mail ad un amico e ci dimentichiamo una virgola nel
contenuto del nostro messaggio esso arriverà a destinazione
uguamente. Se invece facciamo un errore quando scriviamo
l’indirizzo mail il messaggio non arriverà mai al destinatario.
Scrivere un’istruzione in Processing è come scrivere un indirizzo
mail, se non metti la chiocciola o sbagli anche solo un puntino non
funzionerà nulla.
Gli aspetti formali della programmazione sono importanti e non
possono essere tralasciati. Un altro aspetto formale che non
possiamo tralasciare in Processing è che i comandi sono “case
sensitive”. “Size” e “size”non sono la stessa cosa, il comando “size”
deve essere scritto con tutte le lettere minuscole, se non lo facciamo
Processing non interpreta il comando. “Size” per Processing non
significa nulla.
Torniamo ora alla terza riga del nostro breve programma:
background(255);
processing guida introduttiva alla programmazione visuale
8
Possiamo facilmente distiguere il comando “background” il
parametro tra parentesi e il termine della riga di istruzione “;”.
Il comando specifico “background” indica a Processing il colore che
dovrà avere lo sfondo della finestra che abbiamo appena creato. 255
indica il colore bianco.
Una volta terminato di scrivere il nostro programma in tre righe lo
potremo lanciare cliccando sul pulsante RUN. Potremo
interrompere l’esecuzione del nostro programma cliccando sul
pulsante STOP.
Numeri e Variabili
Abbiamo creato il nostro primo breve programma in Processing.
Abbiamo compreso alcuni principi base della programmazione.
Questi principi sono pressochè universali nella programmazione e
comprenderli in processing ci permetterà poi di applicarli a
praticamente qualunque altro linguaggio di programmazione.
Nel nostro primo programma abbiamo visto che i comandi possono
avere dei parametri e che questi parametri si esprimono in numeri.
Nella programmazione è normale però esprimere i numeri anche
attraverso delle variabili.
Queste due espressioni producono lo stesso risultato:
//senza variabili
background(0);
//con variabili
int X = 0;
background (X);
Nel secondo caso abbiamo fatto due operazioni. Con la prima
operazione abbiamo detto al programma di attivare l’uso di una
variabile che abbiamo chiamato “X” e abbiamo assegnato un valore
a questa variabile “0”.
Il risultato è che “background” avrà un valore pari a zero, proprio
come nel primo esempio.
Le variabili sono molto utili nella programmazione proprio perchè
sono “variabili” e quindi il loro valore può cambiare in base a degli
processing guida introduttiva alla programmazione visuale
9
eventi , oppure possono cambiare in base a delle operazioni
matematiche.
Le variabili sono molto utili anche perchè memorizzano dei valori e
permettono di riutilizzarli quando serviranno in futuro.
Esistono diversi tipi di variabili; nel nostro esempio “int” indica una
variabile che può assumere un valore numerico intero (senza valori
dopo la virgola). “float” è un altro tipo di variabile numerica che può
invece contenere anche valori dopo la “virgola”.
Importante: come in quasi tutti i linguaggi legati all’informatica la
virgola che noi utilizziamo nei numeri per indicare i valori decimali,
deve essere sostituita dal punto “.”.
Nei linguaggi di programmazione 10.5 equivale al 10,5 nella
notazione che utilizziamo in Italia.
Da notare che non è possibile fare operazioni matematiche
mescolando due variabili di tipo diverso (una “int” e l’altra “float”).
Nel linguaggio comune della programmazione l’istruzione:
int X = 0;
viene detta inizializzazione o dichiarazione di una variabile. Questo
tipo di istruzioni generalmente vengono messe all’inizio dei
programmi e comunque debbono essere posizionate sempre prima
che si utilizzi la variabile stessa.
La seguente sequenza non funzionerebbe:
background (X);
int X = 10;
Se vogliamo utilizzare la variabile “X” prima la dobbiamo
inizializzare “int X = 10;”.
Una volta che la variabile è stata inizializzata è possibile utilizzarla
tutte le volte che si desidera. Inoltre dopo l’inizializzazione la
variabile può essere “manipolata”.
Nell’esempio seguente osserviamo che:
int X = 10;
X = 6;
background (X);
la variabile “X” è stata prima inizializzata poi successivamente è
stato assegnato un nuovo valore alla variabile “X = 6;”.
processing guida introduttiva alla programmazione visuale
10
Pertanto il valore finale di “background (X);” sarà 6.
Ovviamente per brevità sarebbe stato più intelligente scrivere:
int X = 6;
background (X);
il risultato sarebbe stato identico.
Il nome delle variabili
Abbiamo visto quindi che le variabili hanno un nome. Ho utilizzato
“x” e come primo passagio potrebbe essere anche corretto ma
quandi si scrive un programma più complesso è invece consigliabile
dare un nome “sensato” alle variabili.
Il lungo discorso che ho fatto nelle pagine precedenti riguardo i
commenti vale anche per le variabili.
Ipotizziamo ad esempio di voler disegnare un cerchio attraverso un
programma e ipotizziamo che questo cerchio cambierà di
dimensione durante l’esecuizone del programma stesso.
Potremmo assegnare a questa variabile semplicemente una lettera
“X” oppure “C”, ma se immaginiamo che il nostro programma sarà
abbastanza complesso allora sarà sicuramente meglio utilizzare un
nome della variabile più esteso.
Possiamo chiamare la variabile che gestirà il nostro cerchio ad
esempio “cerchio”. In questo modo quando riapriremo il
programma in futuro oppure qualcun’altro aprirà il nostro
programma il nome della variabile permetterà facilmente di
comprendere di che variabile si tratta e per che cosa viene utilizzata.
Pertanto quando dichiarerò la mia variabile all’inizio del programma
scriverò
int cerchio = 10;
anzichè
int X = 10;
Il termine cerchio ci aiuterà molto in futuro quando il nostro
programma andrà progressivamente coplicandosi. Ma in realtà un
buon programmatore dovrebbe precedere la dichiarazione della
variabile con un commento che spiega a cosa serve quella variabile.
Ad esempio:
processing guida introduttiva alla programmazione visuale
11
// ecco la variabile che gestisce
// il raggio del cerchio
int cerchio = 10;
Il nome delle variabili è sempre meglio che sia “parlante”. Alcuni
nomi però sono inibiti e non possono essere utilizzati per le
variabili.
Ad esempio non posso nominare una variabile “int” perchè facendo
questo complicherei molto la vita a Processing che potrebbe fare
confusione. Infatti “int” è anche un termine assegnato ad un
comando.
Di seguito una lista dei nomi di variabili che non possiamo usare in
Processing:
abstract
assert
boolean
break
byte
case
catch
char
class
const
continue
default
do
double
else
enum
extends
false
final
finally
float
for
goto
if
implements
import
init
instanceof
int
interface
long
native
new
null
package
private
protected
public
return
setup
short
start
static
processing guida introduttiva alla programmazione visuale
12
stop
strictfp
super
switch
synchronizedthis
throw
throws
transient
true
try
update
void
volatile
while
Questo aspetto è comune a praticamente tutti i linguaggi di
programmazione. Un consiglio che posso dare ai programmatori
italiani è proprio quello di dare un nome in italiano alle variabili.
Poichè i comandi tipicamente sono in inglese si eviterà facilmente di
utilizzare un nome vietato.
Esiste poi una lista di variabili che gestisce autonomamente
Processing. Quando ad esempio abbiamo generato la finestra:
size(320, 240);
Processing ha automaticamente immagazzinato in un due variabili
“width” e “height” questi valori. Se in futuro vorremo utilizzare
questi valori potremo utilizzarli richiamando direttamente le
variabili.
Variabili e calcoli matematici
Le variabili normalmente vengono utilizzate anche per effettuare
calcoli matematici. Le operazioni di base che si effettuano sono più
“+”, meno ”-“, per ”*” e diviso “/”.
Normalmente il risultato di un’operazione matematica viene
memorizzato nelle variabili.
Ad esempio:
int x = 2 + 3;
trasferisce il risultato della somma “2+3” nella variabile X al
momento della sua inizializzazione “int”.
Oppure:
int x = 4;
processing guida introduttiva alla programmazione visuale
13
int y = 6;
int s = x + y;
int d = s / 2;
int m = (x * y)-2;
dichiara il valore delle variabili “x” e “y”, poi viene sommato e il
risultato è memorizzato nella varibile “s” (da cui avremo s = 10). In
“d” invece memorizziamo il risultato di della somma precedente
dividendola per 2 (da cui otterremo d = 5).
Infine nella quinta riga abbiamo una vera e propria espressione.
Trasferiamo nella variabile “m” il risultato della moltiplicazione di
“x” per “y” e successivamente, fuori dalle parentesi, sottraiamo 2 (da
cui otteniamo m = 22).
Da notare che il risultato di un calcolo matematico deve sempre
essere associato a una variabile. Infatti se nella terza riga scriviamo
solo:
x + y;
otterremo un errore quando manderemo in RUN il nostro sketch.
L’uso delle parentesi cosi come nella matematica serve per dare la
priorità ai calcoli. Inoltre moltiplicazione e sottrazione hanno la
priorità su addizione e sottrazione.
Le variabili posso essere utilizzate molte volte all’interno della stessa
espressione. A volte siamo costretti a compiere diverse operazioni
ma non ci interessato i risultati intermedi bensì solo il risultato
finale.
Nel seguente programma:
int x = 4;
int y = 6;
int s = x + y;
s = s / 2;
dopo avere calcolato “x+y” e memorizzato il risultato in “s”
utilizziamo nuovamente “s” nella riga successiva per memorizzare il
valore “s” della riga precedente diviso per 2. Operando in questo
modo abbiamo “risparmiato” una variabile però abbiamo perso il
risultato temporaneo della somma “x + y”. Quando Processing
processing guida introduttiva alla programmazione visuale
14
eseguirà la quarta riga trasferirà in “s” il risultato della nuova
operazione (“s/2”) e il precedente valore di “s” sarà perso.
Iniziare a disegnare
Le operazioni matematiche che si possono effettuare in Processing
sono molte di più delle quattro operazioni di base, ma stiamo
procedendo secondo un livello di difficoltà progressivo. Abbiamo
capito come si scrive un’istruzione in Processing e abbiamo capito
l’importanza della sintassi. Inoltre abbiamo introdotto il concetto di
variabile nella programmazione. Questi primi elementi ci
permettono di iniziare a scrivere un programma leggermente più
complesso.
Per fare questo però ci avvarremo dell’aspetto maggiormente
potente in Processing, cioè le funnzionalità grafiche.
Credo che comprendere una formula matematica sia molto più
semplice se il risultato di questa formula viene tradotto in una
dimensione grafica.
Prima quindi di addentrarci nei meandri della programmazione e
dell’uso intensivo della matematica iniziamo quindi ad osservare le
funzionalità grafiche di Processing. La conoscenza delle funzionalità
grafiche faciliterà molto lo sviluppo di formule matematiche più
complesse.
Abbiamo iniziato la nostra programmazione scrivendo tre righe:
//Creiamo una finestra 320 x 240 pixel//
size(320, 240);
background(255);
che, abbiamo visto cliccando su RUN, generano una finestra di
sfondo bianco della dimensione di 320 pixel di larghezza e 240 pixel
di altezza.
Per disegnare qualche cosa dentro questa finestra è necessario prima
di tutto comprendere il concetto di coordinate. L’asse delle X scorre
in orizzontale mentre l’asse delle Y scorre in verticale.
L’angolo in alto a sinistra della nostra finestra ha le coordinate (0, 0).
L’angolo in basso a destra ha coordinate (320, 240). L’angolo in alto
a destra ha coordinate (320, 0) mentre l’angolo in basso a sinistra ha
coordinate (0, 240).
figura 2
disegno delle coordinate
processing guida introduttiva alla programmazione visuale
15
L’istruzione grafica piùsemplice di Processing permette di generare
un punto nello schermo. Questa è la sua sintassi:
point(X, Y);
questo comando grafico ha due parametri, “X” ed “Y” che indicano
le coordnate della finestra nella quale verrà disegnato il punto.
Se ad esempio decidessimo di disegnare il punto esattamente al
centro della finestra che abbiamo appena creato sarà sufficiente
aggiungere una quarta riga:
//Creiamo una finestra 320 x 240 pixel//
size(320, 240);
background(255);
point(160, 120);
Dividendo per due la larghezza e l’altezza della finestra ottengo le
coordinate “X,Y” del punto centrale della finestra.
Per comprendere meglio il funzionamento del sistema delle
coordinate è sufficiente cambiare i valori “X,Y” del comando point.
Da notare che questi valori debbono necessariamente rimanere
all’interno dell’intervallo della finestra stessa.
Per generare più punti nella finestra aggiungo più volte la stessa
istruzione cambiando le coordinate.
Mantenendo fisso uno dei due valori delle coordinate si ottengono
dei punti lungo l’asse verticale o orizzontale a seconda del valore
tenuto fisso.
size(320, 240);
background(255);
//Creiamo tre punti sull’asse verticale
//tenendo il valore “X” stabile
point(160, 60);
point(160, 120);
point(160, 180);
L’aspetto centrale di Processing in quanto strumento didattico è
proprio la facilità con la quale possiamo visualizzare dei principi
matematici e statistici. Le coordinate X,Y le ritroviamo in infiniti
sistemi e rappresentazioni. Manipolare in Processing i valori del
processing guida introduttiva alla programmazione visuale
16
comando “point” permette di comprendere immediatamente in
modo visivo il funzionamento delle coordinate.
Questa guida può essere letta anche come un’introduzione ai
principi della matematica, della programmazione e degli algoritmi,
possiamo vedere Processing come lo strumento più veloce per
comprendere questi principi.
Una volta compreso il principio delle coordinate sarà molto
semplice con processing disegnare tutte le forme geometriche di
base.
Ad esempio questa è la sintassi del comando per disegnare una linea:
line(x1, y1, x2, y2);
Con questo comando viene eseguita una linea che come estremi due
punti individuati con “X1,Y1” e “X2,Y2”.
size(320, 240);
background(255);
//Creiamo una linea diagonale
//che attraversa la finestra
//dall’angolo in alto a sinistra
//all’angolo in basso a destra
line(0, 0, 320, 240);
Per fare una linea in senso orizzontale il parametro Y dei due punti
dovrà rimanere costante. Il seguente comando genera una linea che
attraversa la finestra orizzontalmente alla sua metà.
line(0, 120, 320, 120);
Per disegnare diverse linee è sufficiente mettere un’istruzione dopo
l’altra nello stesso Sketch. Per disegnare diverse linee con dei punti
in comune è sufficiente scrivere più istruzioni dove ogni linea ha due
coordinate uguali alla linea successiva.
//figura composta da due linee
//che hanno un punto in comune
//100,120
line(0, 120, 100, 120);
processing guida introduttiva alla programmazione visuale
17
line(100, 120, 80, 220);
Unendo delle linee possiamo disegnare triangoli, quadrilateri,
rettangoli e linee spezzate.
//triangolo prodotto
//disegnando 3 linee
line(0, 120, 100, 120);
line(100, 120, 80, 220);
line(80,220,0, 120);
Ovviamente però Processing prevede le istruzioni per disegnare
direttamente Triangoli, Quadrilateri, Rettangoli ed Ellissi.
triangle
quad
rect
ellipse
Ecco spiegato di seguito il funzionamento di ogni istruzione:
triangle (X1, Y1, X2, Y2, X3, Y3);
Attraverso i tre punti vengono disegnati i tre lati del triangolo.
quad (X1, Y1, X2, Y2, X3, Y3, X4, Y4);
Attraverso i quattro punti vengono definiti i quattro lati del
quadrilatero. Il quadrilatero che ne deriva può avere anche tutti i lati
diversi e non avere lati paralleli.
Importante però quando si disegna un quadrilatero è di seguire un
ordine dei lati.
Se ad esempio scrivete questa istruzione
quad (1, 1, 50, 10, 100, 100, 130, 100);
succede che anzichè generare un quadrilatero genererete due
trinagoli. Ciò succede perchè nel passaggio dal secondo punto al
terzo e dal terzo al quarto Processing segue l’ordine dei punti e
quindi i lati del quadrilatero si incrocieranno.
processing guida introduttiva alla programmazione visuale
18
Scambiando il terzo punto con il quarto otterremo invece un
quadrilatero:
quad (1, 1, 50, 10, 130, 100, 100, 100);
Per quanto riguarda il rettangolo Processing ragiona in modo
leggermente diverso, ecco la sintassi:
rect(x, y, width, height)
si individua con i parametri “X,Y” l’angolo in alto a sinistra del
rettangolo e successivamente si dichiara la larghezza e l’altezza del
rettangolo. Ovviamente se “width” e “height” hanno lo stesso
valore succede che il rettangolo diventa un quadrato.
Infine ecco l’istruzione per generare ellissi e cerchi:
ellipse (X, Y, width, height);
Con “X, Y” si stabilisce il centro dell’ellisse mentre con “width,
height” si stabiliscono larghezza e altezza dell’ellisse. Se i due
parametri “width, height”sono uguali si ottiene un cerchio perfetto.
Abbiamo quindi visto come si disegnano le figure geometriche di
base con Processing. Gli esempi descritti sopra fanno sempre
riferimento a delle forme “stabili” legate cioè a dei numeri “fissi”.
Volendo effettuare dei disegni più complessi e dinamici potremmo
associare le nostre forme a delle variabili.
Inoltre le forme che abbiamo disegnato fanno sempre riferimento
ad un contesto “neutrale”dove il colore di sfondo è sempre bianco e
le figure sono bianche bordate di nero.
Ad esempio il seguente Sketch
size(320, 240);
background(255);
//Creiamo un quadrilatero
quad (1, 1, 50, 10, 130, 100, 100, 100);
//mettiamo sopra al quadrilatero un cerchio
ellipse (20,20, 50, 50);
processing guida introduttiva alla programmazione visuale
19
produrrà graficamente il quadrilatero che conosciamo e
successivamente sopra di esso un cerchio le cui coordinate del
centro sono “20, 20” ed il cui raggio è 50. Il cerchio come possiamo
vedere ha uno sfondo bianco pertano si sovrappone, coprendolo in
parte, al quadrilatero.
Questo comportamento ci spiega due aspetti di Processing.
Prima di tutto dobbiamo capire che Processing come tutti i linguaggi
di programmazione esegue i comandi leggendoli in sequenza. La
sequenza di esecuzione diventa sempre più importante e strategica
quando si complica lo Sketch.
Inoltre le figure grafiche hanno un riempimento e non sono
trasparenti. Per vedere meglio questo riempimento possiamo
cambiare il colore della finestra.
background(0);
Canbiando il valore di background da 255 (bianco) a 0 (nero)
vediamo ancora maglio che le forme geometriche create hanno un
colore di riempimento.
I numeri compresi tra 0 e 255 rappresentano tutte le gradazioni che
vanno dal nero al bianco, cioè sono dei grigi sempre meno intensi
che alla fine 255 diventa un bianco.
Questa modalità di classificazione dei colori vale anche per il colore
di riempimento delle forme.
Quando questo colore non viene dichiarato Processing stabilisce
autonomamente un colore (questo in informatica viene definito
valore di default).
Per vedere ad esempio quale è il colore di default delle finestre è
sufficiente cancellare l’istruzione background dal nostro sketch.
Mandando in run Processing vediamo che la finestra assume un
colore di sfondo grigio.
I comandi hanno valori di default diversi infatti le forme
geometriche che abbiamo creato hanno un valore di default per il
riempimento che è il bianco (255).
Per cambiare il valore di default per il riempimento delle forme
geometriche si utilizza l’istruzione:
fill ();
questa istruzione deve precedere il comando per la generazione della
forma geometrica.
Il seguente sketch
processing guida introduttiva alla programmazione visuale
20
size(320, 240);
fill (80);
//Creiamo un quadrilatero
quad (1, 1, 50, 10, 130, 100, 100, 100);
//mettiamo sopra al quadrilatero un cerchio
ellipse (20,20, 50, 50);
genera quindi una finestra con un colore di sfondo di default (grigio)
e delle forme geometriche con un colore di sfondo stabilito dal
valore tra parentesi del comando “fill”. 80 indica un grigio scuro.
Il valore fill funziona per tutte le forme geometriche che verranno
generate dopo di esso. Possiamo infatti vedere che sia il quadrilatero
che il cerchio hanno lo stesso riempimento. Qualora volessimo
generare forme geometriche con valori di sfondo diversi dobbiamo
semplicemente mettere dei nuovi comandi fill
size(320, 240);
//Creiamo un quadrilatero
fill (80);
quad (1, 1, 50, 10, 130, 100, 100, 100);
//mettiamo sopra al quadrilatero un cerchio
fill (250);
ellipse (20,20, 50, 50);
Il fill valido è sempre l’ultimo e vale nello sketch finchè non ne
dichiariamo uno nuovo. Il cerchio dello sketch qui sopra è pressochè
bianco (250) il quadrilatero e grigio scuro (80) e se creassimo una
nuoma forma geometrica dopo il cerchio senza specificare un nuovo
fill esso sarebbe 250.
Le forme grafiche hanno altri valori di default. Ad esempio
disegnando le forme geometriche notiamo che il bordo della forma
ha un colore e uno spessore. Il cerchio che abbiamo creato nel
precedente Sketch ha il bordo nero, questo colore è di default e può
essere cambiato mettendo, sempre prima dell’istruzione che genera
la forma geometrica , l’istruzione:
stroke (255);
processing guida introduttiva alla programmazione visuale
21
in questo caso il cerchio avrà un bordo bianco (255) e qualora sia
bianco anche il riempimento ovviamente non avremo percezione del
bordo stesso.
Un modo più corretto per fare scomparire il bordo da una forma
geometrica è l’apposito comando
nostroke (0);
così come possiamo fare scomparire il riempimento con
noFill (0);
Inoltre possiamo anche decidere lo spessore del bordo delle forme
geometriche (e delle linee) attraverso l’istruzione
strokeWeight(4);
dove il valore tra parentesi indica lo spessore del bordo espresso in
pixel. Da notare un aspetto importante: la “W” di Weight è
maiuscola e come ho spiegato nelle prime pagine i comandi sono
“case sensitive” pertanto dobbiamo scriverli tenendo presenti le
maiuscole e le minuscole.
In generale su questo aspetto però l’ambiente di sviluppo di
Processing ci aiuta poichè se per errore digitiamo un comando
errato (es: strokeweight) vediamo che Processing non modifica il
colore del comando stesso lasciandolo nero. Quando invece
digitiamo un comando che per Processing significa qualche cosa (es:
strokeWeight) succede che immediatamente il testo viene cambiato
di colore e diventa marrone.
Da notare infine che in molti linguaggi di programmazione si segue
questa convenzione, la prima parola di un comando si scrive in
minuscolo la seconda parola (attacata) inizia sempre con una
maiuscola, lo stesso vale per l’eventuali terza o quarta parola.
Diversi altri parametri permettono di intervenire sulle forme
geometriche ma per ora abbiamo visto quelli essenziali e possiamo
procedere oltre nel nostro percorso di addestramento alla
programmazione.
In seguito scopriremo come gestire i colori (per ora abbiamo visto
solamente come gestire i grigi, e come gestire ad esempio le
trasparenze nonchè le curve e tante altre cose ...).
processing guida introduttiva alla programmazione visuale
22
Ora però è necessario un nuovo salto nella modalità di lavoro.
Programmare veramente
La programmazione che abbiamo visto fino ad ora è composta da
una serie di comandi messi in sequenza. Processing elabora le
istruzioni una dopo l’altra partendo dalla prima riga e terminando
all’ultima. In pratica Processing legge i programmi che abbiamo
fatto fino ad ora come noi leggiamo i contenuti di un libro.
Abbiamo visto anche il concetto di variabile. Le variabili sono utili
perchè invece di utilizzare sempre i numeri possiamo sostituirli con
delle entità il cui stato varia con lo scorrere del programma.
I disegni che abbiamo fatto fino ad ora sono molto semplici e
sopratutto sono statici. Infatti tutte le istruzioni che abbiamo scritto
vengono elaborate sequenzialmente ma ad una velocità tale percui
quando premiamo il tasto RUN davanti a noi compare una figura
apparentemente statica.
Processing è un’applicazione che si presta bene per fare lavori di tipo
statico (immagini fisse) ma si presta molto bene anche per fare
animazioni.
Inoltre anche nell’elaborazione di immagini statiche potrebbe
succedere che vogliamo produrre molte volte una figura ad intervalli
regolari oppure di dimensioni progressivamene crescenti.
Questa tipologia di problematiche: animazioni e ripetizioni
(iterazioni) possono essere risolte in modo veloce attraverso delle
apposite istruzioni.
Partiamo da un caso molto semplice: all’interno della nostra finestra
vogliamo disegnare dei punti ad intervalli regolari sull’asse
orizzontale, uno ogni 40 pixel.
Disegniamo ora questi punti utilizzando il metodo più semplice che
abbiamo visto.
size(320, 240);
background(255);
//Creiamo sette punti
//sull’asse orizzontale
//tenendo il valore “Y” stabile
point(40, 120);
point(80, 120);
point(120, 120);
point(160, 120);
processing guida introduttiva alla programmazione visuale
23
point(200, 120);
point(240, 120);
point(280, 120);
Abbiamo visto già nelle pagine precedenti tutte le istruzioni che
permettono di generare questo nuovo Sketch. Premendo RUN
vediamo sette punti a intervalli rogolari che attraversano lo schermo
in senso orizzontale.
Ora introduciamo l’uso delle variabili. Stabiliamo una variabile che
chiamiamo “intervallo” e che ha il valore di 40, successivamente
sostituiamo i valori delle coordinate X dei punti con le variabili.
size(320, 240);
background(255);
// dichiaro la variabile
int intervallo = 40;
//Creiamo sette punti
//sull’asse orizzontale
//tenendo il valore “Y” stabile
point(intervallo, 120);
point(intervallo*2, 120);
point(intervallo*3, 120);
point(intervallo*4, 120);
point(intervallo*5, 120);
point(intervallo*6, 120);
point(intervallo*7, 120);
Abbiamo moltiplicato l’intervallo per dei valori progressivamente
maggiori ottenendo esattamente lo stesso risultato del precedente
Sketch. Il coefficiente di moltiplicazione che applichiamo
all’invervallo stabilisce la distribuzione dei punti.
Proviamo quindi a trasformare in variabile anche questo
coefficiente, chiamandola coefficiente.
size(320, 240);
background(255);
// dichiaro la variabile
int intervallo = 40;
// dichiaro la variabile
// coefficiente
int coefficiente = 1;
processing guida introduttiva alla programmazione visuale
24
//Creiamo sette punti
//sull’asse orizzontale
//tenendo il valore “Y” stabile
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
Leggendo con attenzione lo Sketch appena scritto vediamo che esso
è diventato molto più lungo. Infatti per poter incrementare ogni
volta il coefficiente è stata aggiunta l’apposita istruzione
“coefficiente = coefficiente + 1;”. Comunque un primo vantaggio
possiamo coglierlo dal fatto che osservando con attenzione lo sketch
vediamo che le istruzioni sono sempre uguali. Infatti le due righe di
istruzione:
point(intervallo*coefficiente, 120);
coefficiente = coefficiente + 1;
si ripetono sette volte generando i sette punti. Per velocizzare
l’operazione di scrittura dello sketch potremmo scriverlo facendo
“copia” e “incolla” delle due righe fino a ripeterle sette volte.
La logica della programmazione informatica sta esattamente in
questi passaggi:
- concepire tutti i passaggi che portano al risultato
(abbiamo scritto nel primo Sketch tutte le istruzioni che portavano
al risultato desiderato)
- concepire questi passaggi in modo che siano ripetitivi
(abbiamo scritto nel terzo Sketch istruzioni ripetitive che portano al
risultato desiderato)
processing guida introduttiva alla programmazione visuale
25
- trasformare i passaggi da ripetitivi a ricorsivi
(ora trasformeremo le operazioni ripetitive in ricorsive scrivendo un
“ciclo”):
size(320, 240);
background(255);
// dichiaro la variabile
int intervallo = 40;
// dichiaro la variabile
// coefficiente
int coefficiente = 1;
//Creiamo sette punti
//sull’asse orizzontale
//tenendo il valore “Y” stabile
for (coefficiente = 1; coefficiente < 8;
coefficiente = coefficiente+1) {
point(intervallo*coefficiente, 120);
}
L’unico elemento nuovo nello Sketch precedente è esattamente
l’istruzione “for” che ha la seguente sintassi:
for (coefficiente = 1; coefficiente < 8;
coefficiente = coefficiente+1) {
point(intervallo*coefficiente, 120);
}
I principi di ricorsività vengono stabiliti tra parentesi dopo avere
scritto l’istruzione “for”. Tra parentesi troviamo tre elementi
separati da “;”.
Il primo elemento “coefficiente = 1” stabilisce il valore di partenza
del ciclo.
Il secondo elemento “coefficiente < 8” stabilisce il valore di
interruzione del ciclo.
Il terzo elemento stabilisce l’aggiornamento del valore che avverrà
ricorsivamente (l’incremento della variabile) che nel nostro caso è
“coefficiente = coefficiente+1”.
In seguito all’istruzione “for” tra le parentesi graffe vengono messe
le operazioni da compiere durante tutta la durata del ciclo “point
(intervallo*coefficiente, 120)”.
processing guida introduttiva alla programmazione visuale
26
Leggiamo come se fosse scritta in lingua italiana l’istruzione “for”del
nostro ciclo:
Incrementa il coefficiente di una unità e finchè il suo valore è
minore di 7 disegna un punto.
Attraverso le istruzioni di tipo “for” possiamo quindi ripetere
un’operazione finchè non si verifichi una condizione di interruzione.
Abbiamo quindi sintetizzato il nostro sketch, da notare che ora,
qualora volessimo disegnare 100 punti invece di 7 la lunghezza dello
sketch sarebbe sempre la stessa mentre invece nella modalità
precendente avremmo dovuto scrivere 100 righe di codice, una per
punto.
Il seguente Sketch disegna 100 punti, con un intervallo tra un punto
e l’altro di 3 pixel:
size(320, 240);
background(255);
// dichiaro la variabile
int intervallo = 3;
// dichiaro la variabile
// coefficiente
int coefficiente = 1;
//Creiamo sette punti
//sull’asse orizzontale
//tenendo il valore “Y” stabile
for (coefficiente = 1; coefficiente < 101;
coefficiente = coefficiente+1) {
point(intervallo*coefficiente, 120);
}
Per fare questa semplice modifica abbiamo solamente modificato la
variabile “int intervallo = 3;” ed abbiamo cambiato il valore di
interruzione del ciclo “for” con “coefficiente < 100”.
La verifica di interruzione del ciclo ”for” avviene attraverso un
simbolo comunemente conosciuto: “<”.
In processing è possibile anche controllare se un valore è maggiore
“>” oppure se un valore è uguale “==”.
Nel caso di uguale (come in molti linguaggi di programmazione) si
utilizza due volte il
simbolo “=” per evitare che il programma compia un’operazione
sulla variabile.
Pertanto quando scriviamo:
processing guida introduttiva alla programmazione visuale
27
X = 5 trasferiamo il valore “5” nella variabile “X”
Mentre se scriviamo
X == 5 controlliamo se il valore di X è uguale (==) a 5.
La programmazione in Processing ci permette quindi di evitare di
scrivere infinite operazioni descrivendole una ad una. Attraverso i
cicli “for” possiamo ripetere delle operazioni infinite volte
cambiando ogni volta l’operazione grazie all’uso delle variabili.
Le condizioni
Un’altra istruzione (oltre al ciclo “for”) è determinante nel processo
di apprendimento della programmazione. Questa istruzione è “if”.
Continuiamo a lavorare nel nostro precedente Sketch e
modifichiamolo decidendo che i nostri punti devono diventare delle
linee quando il valore del “coefficiente” supera la soglia di 90
(elimino i commenti per risparmiare “carta” visto che sono presenti
nello Sketch precedenti).
size(320, 240);
background(255);
int intervallo = 3;
int coefficiente = 1;
for (coefficiente = 1; coefficiente < 101;
coefficiente = coefficiente+1) {
if (coefficiente > 90) {
line (intervallo*coefficiente, 120,
intervallo*coefficiente, 130);
}
point(intervallo*coefficiente, 120);
}
Abbiamo aggiunto l’istruzione “if”:
if (coefficiente > 90) {
line (intervallo*coefficiente, 120,
intervallo*coefficiente, 130);
}
processing guida introduttiva alla programmazione visuale
28
che controlla se il coefficiente è maggiore di 90 e qualora lo sia
disegna una linea verticale lunga 10 pixel (notare il valore della
coordinata Y che è prima 120 poi 130). Mandando in RUN lo sketch
completo vediamo che Processing disegna 90 punti e poi inizia a
disegnare delle linee.
La gestione delle condizioni nella programmazione è determinante,
infatti ogni volta che verifichiamo se una condizione si verifica
automaticamente creiamo un bivio nel percorso possibile che può
compiere il programma.
Quando al mattino usciamo di casa controlliamo se piove e qualora
stia piovendo prendiamo l’ombrello. In quel momento compiamo
un’operazione di tipo “if”.
Quando all’interno di un programma ad esempio vogliamo gestire le
possibili interazioni con l’utente che lo userà dobbiamo farlo
attraverso delle operazioni “if”. Tutti i software che producono delle
interazioni con l’utente lo fanno ragiornando attraverso dei comandi
di tipo “if”.
I cicli “for” insieme ai controlli “if” sono due elementi centrali della
logica di programmazione (in processing e praticamente in
qualunque altro linguaggio di programmazione).
Il controllo “if” permette anche di gestire la condizione negativa
(detta “else” ossia altrimenti). Pertanto possiamo decidere anche di
cambiare il nosro sketch così come segue:
size(320, 240);
background(255);
int intervallo = 3;
int coefficiente = 1;
for (coefficiente = 1; coefficiente < 101;
coefficiente = coefficiente+1) {
if (coefficiente > 90) {
line (intervallo*coefficiente, 120,
intervallo*coefficiente, 130);
}
else {
point(intervallo*coefficiente, 120);
}
}
Oltre al controllo precedente (“if coefficiente > 90”) abbiamo
aggiunto la verifica della condizione negativa “else”. In questi
passaggi è importante seguire anche l’uso delle parentesi poichè se
processing guida introduttiva alla programmazione visuale
29
utilizzate in modo errato producono degli errori in fase di
esecuzione.
Rispetto all’uso delle parentesi vale sempre una regola semplice: le
parentesi aperte debbono essere tante quante le parentesi chiuse.
Inoltre le parentesi sono sempre legate, quindi se si apre una
parentesi tonda si deve chiudere la parentesi tonda. Quando si apre
una graffa si deve chiudere la graffa.
Inoltre le parentesi possono essere nidificate, messe cioè una dentro
l’altra.
Nello Sketch sopra ad esempio abbiamo messo dentro alle parentesi
del ciclo “for” (che quindi inglobano il resto delle istruzioni) le
parentesi relative ad “if” e ad “else”. Possiamo dire che abbiamo
messo due piccole scatole (“if” e “else”) dentro una scatola più
grande (“for”).
Programmare le animazioni
Le istruzioni che abbiamo visto fino ad ora ci hanno permesso di
capire i principi base della programmazione. Per generare delle
forme grafiche è sufficiente scrivere le specifiche istruzioni. Le
forme grafiche hanno sempre delle coordinate e dei valori (colore,
spessore...) che possono essere espressi in numeri o attraverso delle
variabili.
L’esecuzione delle istruzioni da parte di Processing procede
linearmente a meno che, attraverso le istruzioni for non realizziamo
dei cicli.
Nel caso in cui volessimo però realizzare delle animazioni dobbiamo
ragionare in modo diverso.
Un’animazione è composta da fotogrammi (immagini fisse)
successivi. L’esecuzione dei fotogrammi ad una velocità sufficiente
genera un effetto di animazione nel nostro cervello.
Processing è un software che ci permette di disegnare attrvaerso le
istruzioni grafiche e ci permette anche di disegnare in movimento.
Riconfiguriamo ora lo Sketch realizzato precedentemente dandoci
un nuovo obiettivo. Produrre attraverso un’animazione dei punti
successivi che compaiono progressivamente.
Per ottenere questo nuovo effetto dobbiamo utilizzare le istruzioni
che permettono di gestire le funzioni:
// configuro i parametri
// di esecuzione
void setup () {
processing guida introduttiva alla programmazione visuale
30
size (320,240);
background (255);
}
int intervallo = 0;
// definisco la funzione
// dentro la funzione
// metto le istruzioni ricorsive
void draw (){
frameRate (1);
point(intervallo, 120);
intervallo = intervallo + 10;
}
Le funzioni utilizzate in questo nuovo Sketch sono due:
void setup () {}
void draw () {}
Con “void setup” vengono definite tutte quelle parti del programma
che rimarranno effettive durante la sua esecuzione. Le istruzioni
interne alla funzione “void setup” vengono eseguite una sola volta.
Infatti dentro le parentesi “{}” sono state messe le due istruzioni
tipiche di ogni Sketch per la definizione della finestra e del suo
colore di sfondo. Inoltre è stata anche messa l’inizializzazione della
variabile “intervallo” che è necessaria un’unica volta.
Con “void draw”viene invece definita la funzione ricorsiva che verrà
eseguita ricorsivamente senza sosta. “frameRate (1);” stabilisce la
velocità dell’animazione che ho impostato ad 1 fotogramma al
secondo in modo al fine di cogliere bene gli effetti dello Sketch. Poi
metto l’istruzione per disegnare il punto e l’istruzione per spostare
di intervalli regolari il punto stesso (intervallo = intervallo + 10).
Quando verrà mandato in RUN lo Sketch si otterrà un’animazione
alla velocità di un frame al secondo dove compare un nuovo punto
ogni frame. Questo punto (grazie al contatore) avrà ad ogni frame
una coordinata Y incrementata di 10.
Mandando in RUN lo Sketch così come è stato configurato succede
che i punti creati nel fotogramma precedente rimangono persistenti
nel video pertanto ad ogni fotogramma avremo un punto in più.
Qualora invece volessimo avere un effetto di spostamento del punto
dovremmo ad ogni nuovo frame cancellare il punto creato nel
fotogramma precedente. Per fare questo è sufficiente spostare
processing guida introduttiva alla programmazione visuale
31
l’istruzione “background (255);”dalla funzione “setup” alla funzione
“draw”.
Mandando nuovamente in RUN lo Sketch modificato notiamo che il
punto del frame precedente scompare ed abbiamo un effetto di
movimento (anche se molto a scatti e lento).
Per velocizzare il movimento è sufficiente modificare i parametri
frameRate (lo impostiamo a 5 poi a 15). Per dare maggiore fluidità è
sufficiente abbassare l’incremento costante della variabile
“intervallo”; anzichè 10 mettiamo 3 poi 1.
Continuando a modificare questi due parametri possiamo capire
sempre meglio il loro uso. Da ricordare che nel cinema e nella
televisione si lavora all’incirca ad una frequenza di 25 fotogrammi al
secondo.
Processing ha un valore di default del “frameRate” di 60. Pertanto se
all’interno della funzione “draw” non dichiariamo una velocità
questo valore sarà automaticamente impostato a 60 (molto veloce).
Da notare infine che, mandando in esecuzione lo Sketch, il punto si
sposta progressivamente da sinistra a destra finchè non scompare. In
realtà, pur scomparendo il punto Processing continua ad elaborare
lo Sketch incrementando il valore “intervallo” anche oltre la
dimensione della finestra dichiarata in “size”. Questo aspetto dovrà
essere tenuto presente quando verranno programmati degli Sketch
sempre più complessi poichè in termini di elaborazione essi
impegnano il computer pur non generando alcun effetto visibile.
Farsi in casa una funzione
I processi base della programmazione sono stati introdotti. Le
funzioni sono molto importanti poichè permettono di eseguire in
modo ricorsivo delle operazioni.
La programmazione in Processing permette anche di definire delle
funzioni da richiamare quando se ne ha bisogno.
Ad esempio possiamo definire una funzione che disegna due punti
che si muovono da sinistra a destra.
Costruisco una funzione come segue:
void punti () {
// con il controllo if
// faccio in modo di ripartire
// ogni volta che esco dallo schermo
if (intervallo > 320) {
intervallo = 10;
processing guida introduttiva alla programmazione visuale
32
}
intervallo = intervallo + 10;
point (intervallo, 120);
point (intervallo +1, 118);
}
dopo l’istruzione che introduce le funzioni (void) viede dato un
nome alla funzione stessa. In questo caso “punti”. Poi per vedere
l’effetto in modo continuativo utilizzo anche una istruzione if che
praticamente controlla se i punti hanno superato la dimensione dello
schermo “if (intervallo > 320)”. In caso affermativo riporto la
variabile “intervallo” al suo valore di partenza (intervallo = 10;) e
quindi i punti riappariranno nello schemo a sinistra in modo infinito.
Le due istruzioni “point” definiscono la posizione dei due punti che
scorreranno in senso orizzontale (infatti come coordinata X hanno
una variabile mentre come coordinata Y hanno un numero fisso).
L’utilità delle funzioni definite sta nel fatto che possono essere
richiamate quando sono necessarie. Pertanto una volta definite
potranno essere utilizzate molte volte.
Di seguito uno sketch che richiama la funzione “punti” (tolgo i
commenti ricorsivi dallo Sketch per brevità).
int intervallo = 10;
void setup () {
size (320,240);
}
void draw (){
frameRate (15);
background (255);
punti ();
}
void punti () {
if (intervallo > 320) {
intervallo = 10;
}
intervallo = intervallo + 10;
point (intervallo, 120);
point (intervallo +1, 118);
processing guida introduttiva alla programmazione visuale
33
}
Leggendo il contenuto della funzione “void draw ()” vediamo il
richiamo alla funzione creata “punti ();”. Per richiamare una
funzione creata è sufficiente quindi scrivere il nome della funzione e
mettere le due parentesi tonde e la virgola.
Il flusso di esecuzione dello Sketch salterà quindi alla funzione
“punti” e la scorrerà come se fosse un sottoprogramma. Terminata
la funzione Processing tornerà a leggere l’istruzione subito dopo il
richiamo. Da ricordare che tutte le istruzioni della funzione “void
draw ()” sono eseguite da processing in modo infinito.
E’ comunque possibile interrompere questo ciclo infinito attraverso
l’istruzione “noLoop ();” sia in un punto specifico durante
l’esecuzione della funzione “draw” sia come caratteristica generale
dello sketch mettendo l’istruzione nell’area “setup”.
Volendo far ripartire il loop infinito di “draw” è invece sufficiente
mettere l’istruzione “loop ();” nel punto desiderato.
Variabili, funzioni, interazioni (if) e cicli rapresentano la base della
programmazione. Chi ha letto e compreso tutto ciò che è scritto
nelle pagine precedenti può tranquillamente dire in giro che conosce
i rudimenti della programmazione.
processing guida introduttiva alla programmazione visuale
34
Seconda Parte
I colori
Molte istruzioni sono state volontariamente tralasciate nella prima
parte del testo perchè l’intento era far comprendere i principi base e
successivamente incrementare la conoscenza intorno ad essi.
Ad esempio nella Prima parte ho descritto il metodo utilizzato in
Processing per definire il bianco, il nero e tutte le tonalità di grigio
che stanno in mezzo.
Traducendo in termini informatici e matematici la modalità di
classificazione utilizzata da Processing per le scale di grigio possiamo
dire che vengono utilizzati 8 bit. Infatti 8 bit permettono di ottenere
28 (256) combinazioni diverse (da 0 a 255).
Il criterio che processing utilizza per i colori è praticamente lo stesso
solamente che applica la scala ai tre colori primari utilizzati per
classificare i colori negli schermi (anche quelli televisivi). Questi
colori sono Il Rosso il Verde (Green) e il Blu, il metodo viene infatti
chiamato RGB.
Processing utilizza 8 bit per classificare ognuno dei tre colori primari
del metodo RGB.
Vediamo prima di tutto un semplice Sketch per capire meglio il
metodo:
size (320, 240);
fill(255, 255, 255);
ellipse (50, 50, 20, 20);
Lo Sketch produce un cerchio (ellipse) di colore bianco poichè nella
istruzione “fill” sono stati impostati i parametri RGB al massimo
valore (255, 255, 255). Ne consegue che se impostiamo tutti e tre i
parametri al mimimo otteniamo il nero (0, 0, 0). Questo metodo è
anche detto additivo.
I tre numeri hanno una posizione fissa, il primo indica il Rosso, il
secondo il Verde e il tezo il Blu. Di seguito una breve tabella con
alcuni esempi di colore ottenuti attraverso il metodo RGB:
(255, 0, 0) = Rosso
(0, 255, 0) = Verde
(0, 0, 255) = Blu
processing guida introduttiva alla programmazione visuale
35
(255, 255, 0) = Giallo
(150, 150, 150) = Grigio
(250, 200, 200) = Rosa
Le combinazioni possibili prodotte da 24 bit sono circa 16 milioni
di colori.
Il metodo RGB può essere applicato in sostituzione del metodo a 8
bit. Ad esempio per tornare allo Sketch precedente potremmo
stabilire di voler disegnare un cerchio bianco con bordo rosso. Per
fare questo utilizziamo un’istruzione che abbiamo già visto “stroke”
però in questo caso dichiariamo i 3 colori primari.
size (320, 240);
fill(255, 255, 255);
stroke (255, 0, 0);
ellipse (50, 50, 20, 20);
Inoltre aggiungendo l’istruzione background possiamo anche
stabilire il colore di sfondo della finestra. Ad esempio se allo sketch
precedente aggiungiamo l’istruzione “background (0, 0, 0)” dopo
l’istruzione “size”, otteniamo uno sfondo verde.
Trasparenza
Processing permette anche di gestire un quarto parametro per
gestire i colori. Anche questo quarto parametro viene gestito con
uno spettro di 8 bit, esso è la trasparenza (anche detto canale alpha).
Vediamo uno Sketch:
size (320, 240);
fill(0, 0, 255, 200);
ellipse (50, 50, 20, 20);
fill(255, 0, 0, 100);
ellipse (40, 40, 20, 20);
fill(255, 0, 255, 50);
ellipse (20, 20, 50, 50);
Il precedente Sketch produce tre cerchi con colori diversi e gradi di
riempimento diversi (il quarto parametro dell’istruzione “fill”).
processing guida introduttiva alla programmazione visuale
36
Quando il canale Apha è impostato a 0 la figura risulta
completamente trasparente mentre quando il canale è impostato a
255 la figura risulta essere piena.
Il grado di trasparenza è particolarmente utile quando si hanno delle
figure sovrapposte e si vuole lasciare trasparire le figure sottostanti.
Eseguendo il precedente Sketch possiamo notare che i tre cerchi
sono sovrapposti secondo l’ordine definito nella scrittura dello
Sketch: il primo cerchio risulta essere più in fondo e vicino allo
sfondo, mentre l’ultimo cerchio risulta essere più in superficie e
quindi sopra i due cerchi scritti precedentemente.
Il grado di trasparenza è applicabile anche ai grigi. Ecco una tabella
esplicativa delle possibili situazioni, riportata all’istruzione “fill” ma
estensibile a “background”:
fill (100); = riempimento grigio
fill (100, 50); = riempimento grigio con un alto livello di trasparenza
fill (255, 0, 0); = riempimento con metodo RGB
fill (255, 0, 0, 120); = riempimento con metodo RGB e un medio
livello di trasparenza
Un’ultima cosa interessante sui colori riguarda le variabili. E’
possibile definire delle variabili di tipo colore e successivamente
richiamare il colore direttamente scrivendo il nome della variabile.
color rosso = color(255, 0, 0);
fill(rosso);
Ad esempio nelle due righe sopra ho definito il colore rosso e
successivamente lo richiamo all’interno di un parametro fill.
Questà opportunità permette di gestire colori particolari dei quali
magari si è già provata in passato la combinazione. In questo modo
mettendo all’inizio dello Sketch il codice del colore sarà più facile in
seguito nello Sketch richiamarlo.
Nei semplici Sketch questo tipo di funzionalità potrebbero sembrare
inutili, ma quando si inizia a scrivere degli Sketch lunghi centinaia di
righe ci si accorge dell’utilità di queste funzioni (nonchè dei
commenti “//”).
Il caso
Quando si realizza arte con il computer i colori sono ovviamente
determinanti. Designare senza colori è molto più difficile e
limitativo. Mentre alcuni tipi di disegni possono essere facilmente
processing guida introduttiva alla programmazione visuale
37
riprodotti anche in scale di grigio, altri tipi di rappresentazione
necessitano dei colori. Se ben usata, l’opzione dei colori permette di
ottenere dei risultati e delle rappresentazioni visive molto più
efficaci.
C’è un altro aspetto concettuale che riguarda la programmazione che
è altrettanto determinante: la casualità (random).
Generare dei numeri a caso attraverso il computer permette di
ottenere delle forme visuali molto più credibili che non utilizzando
delle rigide formule trigonometriche.
Le numerazioni casuali sono molto utili ad esempio quando si vuole
simulare un movimento di un “soggetto” organico oppure quando si
vuole disporre in modo naturale degli oggetti.
Ad esempio vuolendo simulare una distesa d’erba potremmo in
teoria decidere di mettere un filo ogni 4 pixel ma questa disposizione
così “rigida” e costante darebbe immediatamente un effetto estetico
di artificialità all’immagine risultante. Se invece disponiamo i fili
d’erba in modo casuale entro un certo intervallo (tra 1 e 6 pixel)
otteniamo un effetto naturale nella distribuzione dell’erba stessa.
Inoltre la casualità è molto importante anche quando si vogliono
gestire dei giochi. Tutti gli eventi a partire da un lancio di moneta o
di dado possono essere gestiti attraverso la generazione di un evento
casuale nel computer.
La casualità ha quindi uno spazio importante nella generazione di
immagini e nella gestione delle animazioni fatte con Processing e
con qualunque altro software.
Da notare inoltre che la casualità in quanto tale non è gestibile dai
computer. Infatti i computer ragionano in base a regole molto rigide
e cicliche e quando gli si chiede di generare un numero casuale essi
hanno difficoltà e quindi vanno alla ricerca di eventi da misurare.
Il movimento del mouse è un tipico evento misurato dal computer
che poi rielaborato più volte produce un numero casuale.
Questo aspetto così complesso per il computer è completamente
invisibile agli utenti ma è emblematico di quanto sia ritenuto
importante il fattore casuale nella programmazione. Nonostante il
computer non sia “geneticamente” in grado di produrre eventi
casuali, gli si chiede di gestirli perchè attraverso questa casualità si
possono simulare infiniti eventi.
Modifichiamo quindi l’ultimo Sketch della prima parte utilizzando
un fattore casuale:
int intervallo = 10;
void setup () {
processing guida introduttiva alla programmazione visuale
38
size (320,240);
}
void draw (){
frameRate (5);
background (255);
punti ();
}
void punti () {
if (intervallo > 320) {
intervallo = 10;
}
intervallo = intervallo + int (random (20));
point (intervallo, 120);
point (intervallo +1, 118);
}
Nella funzione “void punti” ho corretto la linea che calcola il salto
che i punti devono compiere ad ogni nuovo frame:
intervallo = intervallo + int (random (20));
Precedentemente il valore di incremento era “10” mentre ora il
valore di incremento (che definisce lo spostamento dei punti) sarà
un valore casuale compreso tra zero e 20 (int (random (20)); ).
“random (20); genera un numero casuale con virgola (di tipo
“float”) compreso tra 0 e 20. L’istruzione “int ()” serve ad
arrotondare i numeri con decimali in numeri interi.
Questa istruzione “int” è necessaria in quanto Processing non
permette di mescolare numeri con virgola (di tipo float) con numeri
interi (di tipo int).
Mandando in RUN lo Sketch vediamo che ora i punti si spostano
sempre da sinistra a destra ma procedendo in modo irregolare a
volte hanno delle accelerazioni mentre altre volte procedono
lentamente. Questo andamento è casuale e lanciando più volte lo
Sketch si otterranno sempre risultati diversi.
Osservando i punti compiere questo tipo di movimenti abbiamo un
effetto di movimento che suscita molta più curiosità, la sensazione
che dona questo tipo di movimento è più organica e “viva” che non
il movimento rettilineo uniforme del precedente Sketch. Per
modificare l’effetto degli scatti possiamo agire su diversi parametri.
Aumentando il valore di random (20) otteniamo scatti sempre più
processing guida introduttiva alla programmazione visuale
39
variegati, mentre otteniamo scatti meno evidenti mettendo dei valori
più bassi.
Inoltre, aumentando il “framerate” otteniamo maggiore velocità
dell’animazione con più fluidità nel movimento dei punti.
Interveniamo nuovamente sullo Sketch al fine di aumentare l’effetto
organico del movimento:
int intervallo = 10;
void setup () {
size (320,240);
}
void draw (){
frameRate (10);
background (255);
punti ();
}
void punti () {
if (intervallo > 320) {
intervallo = 10;
}
intervallo = intervallo + int (random
(5));
point (intervallo, int (random (118,
121)));
point (intervallo +1, int (random (116,
119)));
}
Ora, analizzando la funzione “void punti” vediamo che ho inserito
un fattore di casualità anche nello spostamento sulla coordinata Y.
Pertanto i punti si sposteranno anche leggermente in alto o in basso
durante il loro consueto movimento verso destra.
Analizzando l’istruzione vediamo che tra parentesi questa volta ci
sono due parametri “int (random (116, 119))”. Quando l’istruzione
random contiene due parametri significa che è stato definito un
parametro inferiore e un parametro superiore dell’intervallo casuale.
Nello Sketch precedente, il valore di Y 120 per il primo punto, ora
invece sarà un valore casuale compreso tra 118 e 121.
processing guida introduttiva alla programmazione visuale
40
Mandando in RUN questo ultimo Sketch vediamo che i due punti
spostandosi leggermente anche in alto e in basso avranno un effetto
ancor più organico. Sembreranno volare come due mosche.
Più avanti affronteremo ancor più approfonditamente questo
concetto. Per il momento l’utilizzo della funzione “random” sarà
molto utile perchè ci permetterà di osservare degli esempi più
complessi e variegati, a volte dai comportamenti inattesi (perchè
casuali).
Curve
Abbiamo già esplorato le forme grafiche di base di Processing
(point, line, rect, triangle, quad, ellipse). Osservando i cicli e le
funzioni abbiamo capito che possiamo assegnare le coordinate di
queste forme geometriche a delle variabili anche casuali.
Processing permette anche di generare delle curve secondo un
metodo detto di Bezier.
In pratica possono essere dichiarate, oltre ai due punti di inizio e
fine della curva, anche le tangenti ai due punti.
Vediamo un esempio scrivendo il seguente Sketch e mandandolo in
RUN:
size (320, 240);
noFill ();
bezier(10, 20, 100, 5, 280, 155, 10, 175);
Il punto di inizio e di fine della curva sono la prima e la quarta
coordinata dell’istruzione. La seconda e la terza coordinata indicano
invece le tangenti.
Per capire meglio cosa siano le tangenti consiglio di aggiungere due
istruzioni in grado di visualizzarle:
size (320, 240);
noFill ();
bezier(10, 20, 100, 5, 280, 155, 10, 175);
line (10,20, 100,5);
line (10,175, 280,155);
Grazie alle due linee appena disegnate possiamo ora vedere le
tangenti. Da notare che la curva risultante dalle nostra istruzioni
tende ad essere più accentuata verso il basso.
processing guida introduttiva alla programmazione visuale
41
Osservando la tangente più in basso comprendiamo il motivo. La
tangente è molto più “lunga” pertanto essa “attrae” molto di più la
curva.
Semplificando possiamo vedere la curva di Bezier come se fosse un
elastico: con la prima e la quarta coordinata vengono fissati
(inchiodati) i punti di inizio e fine dell’elastico. Attraverso la seconda
e terza coordinata si “attrae” l’elastico. Quanto più lontane sono le
coordinate di attrazione tanto più l’elastico sarà teso e quindi la
curva sarà più accentuata.
Per avere prova della desrcizione appena effettuata scrivete la
seguente istruzione:
bezier(10, 20, 10, 20, 10, 175, 10, 175);
Il punti di tiraggio dell’elastico sono ora gli stessi dei punti di
terminazione dell’elastico stesso. Ne risulta che la curva di Bezier è
una linea retta (perchè il “tirante” non è attivo avendo le stesse
coordinate del punto).
Attraverso questo metodo possiamo disegnare praticamente
qualunque tipo di curva. Questa funzionalità risulterà
particolarmente utile quando vorremo generare delle forme
organiche che molto difficilmente hanno spigoli e angoli netti.
Lo Sketch di seguito ci mostra il variare di una curva di bezier al
variare delle coordinate delle tangenti:
int contatore = 10;
void setup () {
size (320,240);
}
void draw (){
frameRate (10);
background (255);
//incremento il contatore
contatore = contatore + 1;
// definisco la curva di bezier
// associando le tangenti
// a un contatore per osservare
// il cambiamento della curva
bezier (10,10, contatore, 10, contatore,
200, 60,200);
}
processing guida introduttiva alla programmazione visuale
42
Osservando infine il risultato delle nostre curve notiamo che esse
hanno sempre un effetto di scalettatura. Questo effetto (detto
aliasing) può essere eliminato attraverso l’istruzione “smooth ();” da
mettere all’inizio dello Sketch.
L’effetto sarà di una curva molto più “morbida”. In termini
elaborativi questa gradevole funzionalità estetica di
ammorbidimento aumenterà l’impegno del computer. Ovviamente il
fenomeno avverrà quando avremo disegnato molte curve e avremo
delle animazioni molto veloci.
Complichiamo ulteriormente il nostro lavoro introducendo anche
un fattore di casualità nella generazione della curva. Questo esercizio
è utile perchè viene formulato in modo nuovo uno Sketch
contenente solo funzionalità già viste.
Lo Sketch mandato in RUN genera una curva di bezier che nel
tempo si espande verso destra o verso sinistra seguendo la casualità:
int contatore = 10;
// la variabile casuale
float ai = 1;
void setup () {
size (320,240);
smooth ();
}
void draw (){
frameRate (10);
background (255);
// genero un numero casuale
ai = random (1);
// controllo il numero “estratto”
if (ai > 0.5) {
contatore = contatore + 2;
bezier (100,10, contatore, 10, contatore,
200, 120,200);
}
else {
contatore = contatore - 2;
bezier (100,10, contatore, 10, contatore,
200, 120,200);
}
}
processing guida introduttiva alla programmazione visuale
43
La variabile “ai” è legata alla generazione di un numero casuale (con
decimali e quindi di tipo float) compreso tra 0 e 1. La probalità che
questo numero sia superiore o inferiore a 0.5 è del 50%.
Tendenzialmente quindi avremo una curva che si muove
casualmente verso destra e verso sinistra che però
probabilisticamente tende ad essere stabile (cioè tende a ritornare
alla sua posizione di partenza. Modificando l’istruzione “if (ai >
0.5)” ad esempio in “if (ai > 0.4)” altereremo probabilisticamente
rapporto e quindi la curva tenderà a modificarsi verso una direzione.
I vettori
Quando nella programmazione si parla di vettori non ci si riferisce a
delle forme grafiche bensì a dei contenitori. Abbiamo già visto nella
prima parte il tipo di contenitori più diffusi nella programmazione:
le variabili.
I vettori sono delle variabili concatenate in sequenza. Il termine
inglese per definire i vettori è Array e questi sono alcuni esempi di
istruzioni:
int[] vettore;
float [] vettore2;
Nel primo caso abbiamo la dichiarazione di un vettore che conterrà
dei valori interi mentre nel secondo caso abbiamo la dichiarazione di
un vettore che conterrà dei valori con virgola.
Una volta dichiarato il tipo di vettore è necessario inizializzarlo:
vettore = new int[50];
vettore2 = new float[150];
Nel primo caso abbiamo inizializzato un vettore che conterrà un
massimo di 50 valori diversi mentre nel secondo caso abbiamo
inizializzato un vettore che ne conterrà 150.
Queste dimensioni sono normali in molti tipi di programmi e questo
è proprio il motivo per il quale si usano i vettori anziche le variabili.
Nel caso in cui si vogliano immagazzinare 50 informazioni usando le
variabili sarebbe necessario inizializzare 50 diverse variabili. I vettori
sono quindi il modo più elegante e rapido per organizzare i dati
all’interno di un programma. Troviamo i vettori praticamente in tutti
i linguaggi di programmazione.
processing guida introduttiva alla programmazione visuale
44
Vediamo ora uno Sketch che utilizza i vettori:
size (320, 240);
smooth ();
noFill ();
int[] curva = new int[10];
// ciclo per riempire l'array
for (int cicli = 0; cicli < 10; cicli = cicli +1) {
curva[cicli] = int (random (200));
}
// ciclo di lettura dell'array
for (int cicli = 0; cicli < curva.length; cicli =
cicli +1) {
bezier(curva[cicli], 0, curva[cicli], 100, 200,
240, 240, 240);
}
// secondo ciclo di lettura dell'array
for (int cicli = 0; cicli < curva.length; cicli =
cicli +1) {
ellipse (curva[cicli], 5, 10, 10);
}
Nella quarta riga osserviamo l’struzione di inizializzazione dell’array:
“int[ ] curva = new int[10];” che sarà quindi composto da numeri
interi e si chiamerà “curva”.
Subito dopo leggiamo un ciclo “for” che ha la funzione di riempire
l’array. Il ciclo compie 10 “giri” e mette in ogni casella dell’array un
valore casuale compreso tra 0 e 200 (“curva[cicli] = int (random
(200))”).
Successsivamente abbiamo due altri cicli. Con il primo ciclo
vengono disegnate 10 curve i cui parametri sono letti dall’array
precedentemente creato ( “bezier(curva[cicli], 0, curva[cicli], 100,
200, 240, 240, 240)”).
Da notare che il parametro di chiusura del ciclo “for” viene stabilito
attraverso un controllo della lunghezza dell’array (“cicli <
curva.length”). Curva.lenght dichiara infatti la lunghezza dell’array
che avevamo chiamato “curva”.
Il secondo ciclo di lettura dell’array è simile al primo con la
differenza che vengono disegnati dei cerchi in corrispondenza del
termine superiore delle curve create precedentemente.
Questo secondo ciclo è stato creato appositamente per dimostrare
l’utilità di un array. Infatti nel secondo ciclo è stato riletto tutto il
processing guida introduttiva alla programmazione visuale
45
contenuto memorizzato nell’array e che volendo potrebbe essere
ulteriormente letto per funzioni future.
L’array quindi ci permette di immagazzinare grandi quantità di dati
evitando di dover creare numerose variabili. Inoltre grazie alla loro
sequenzialità gli array facilitano l’accesso per la lettura e la scrittura
attraverso i cicli.
Il seguente Sketch compie le stesse funzioni del precedente in
modalità “continuous” generando un effetto di animazione.
In questo caso il vettore viene riempito e svuotato automaticamente
ad ogni nuovo ciclo automatico di “void draw”.
int[] curva = new int[10];
void setup () {
size (320, 240);
smooth ();
noFill ();
frameRate (10);
}
void draw () {
// azzero lo schermo
background (255);
// ciclo per riempire l'array
for (int cicli = 0; cicli < 10; cicli = cicli +1) {
curva[cicli] = int (random (200));
}
// ciclo di lettura dell'array
for (int cicli = 0; cicli < curva.length; cicli =
cicli +1) {
bezier(curva[cicli], 0, curva[cicli], 100, 200,
240, 240, 240);
}
// secondo ciclo di lettura dell'array
for (int cicli = 0; cicli < curva.length; cicli =
cicli +1) {
ellipse (curva[cicli], 5, 10, 10);
}
}
Notiamo nello Sketch precedente che ad ogni inizio di ciclo viene
pulito lo schermo attraverso l’istruzione “background (255);”. Se
togliamo questa istruzione vedremo che le curve si sovrapporranno
progressivamente andando a formare dopo diversi secondi un intero
spicchio nero. Le ultime sezioni bianche che rimangono sono i
processing guida introduttiva alla programmazione visuale
46
numeri compresi tra zero e 200 che non sono mai stati generati.
Probabilisticamente potrebbero passare anche diversi minuti senza
che la funzione random generi un numero.
processing guida introduttiva alla programmazione visuale
47
Terza Parte
Il testo
Processing, come tutti i linguaggi di programmazione, permette di
gestire il testo. I due comandi più importanti sono:
char ();
String ();
Qesti due comandi sono in realtà due nuove tipi di variabili. La
variabile di tipo “char” può contenere un unico carattere mentre la
variabile di tipo “String” può contenere intere parole o frasi.
Per assegnare un carattere a una variabile si scrive:
char carattere = 'F';
In questo modo la lettera “F” viene memorizzata nella variabile
“carattere”.
Per assegnare una parole o una frase a una variabile si scrive:
String testolungo = “manuale di Processing”;
Da notare che “String” inizia con la lettera grande mentre “char”
inizia con la lettera piccola. Da ricordare che i comandi di
Processing debbono essere scritti tenendo conto anche di maiuscole
e minuscole.
Inoltre da notare che l’istruzione Char richiede gli apici (‘) per
evidenziare il carattere mentre l’istruzione String richiede le
virgolette (“). String può contenere anche testi lunghi un inico
carattere.
Nell’informatica esiste una tabella di corrispondenza tra i caratteri e i
numeri. Praticamente ogni lettera dell’alfabeto è stata classificata con
un numero in modo sequenziale. Questa tabella di corrispondenza si
chiama ASCII e ad esempio la lettera A corrisponde al numero 65.
La lettera B corrisponde al numero 66 e così via.
Questa tabella di corrispondenza è indispensabile poichè senza di
essa il computer (che ragiona per numeri) non potrebbe elaborare i
testi. Le variabili di tipo “char”, essendo lunghe un unico carattere,
possono essere ricondotte ai numeri e viceversa.
Se ad esempio scriviamo:
processing guida introduttiva alla programmazione visuale
48
char carattere = ‘F’;
int numero = carattere;
La variabile “carattere” viene riempita con il valore “F”, poi con la
seconda istruzione la variabile “numero” viene riempita con il
numero corrispondente alla lettera F (70) secondo il codice ASCII.
Questa operazione di conversione bidirezionale dei numeri in lettere
e delle lettere in numeri è possibile solamente attraverso l’istruzione
“char”. Con l’istruzione “String” essendo essa potenzialmente
associata a testi più lunghi di una lettera ciò non è possibile.
Attraverso l’espressione “char ()” possiamo richiamare direttabente
il codice ASCII del carattere. Ad esempio se scriviamo:
char lettera = char(70);
Otteniamo che la variabile “lettera” viene associata con la lettera
“F” (avente come codice ASCII il numero 70).
L’istruzione “String” permette di fare operazioni sul testo. Se ad
esempio associamo due variabili a due diverse parole,
successivamente possiamo attaccare (sommare) le due parole.
String prima = “Manuale di “;
String seconda = “Processing”;
String somma = prima + seconda;
La variabile “somma” avrà come risultato “Manuale di Processing”.
Da notare che dopo l’espressione “Manuale di” è stato lasciato
appositamente uno spazio in modo che esso risulta presente nella
somma delle due variabili.
Il modo più velore per vedere il risultato di queste operazioni sule
variabili testuali (ma anche per quelle numeriche) è l’uso
dell’istruzione “println(somma);” Questa istruzione “println” mostra
un valore nella finestra della console. La stessa finestra dell’ambiente
di sviluppo dove ci appaiono gli errori. Questa finestra è utile quindi
anche quando si sta lavorando ad un programma e si voglieno
controllare dei valori intermedi e temporanei di alcune variabili.
Caratteri sullo schermo
Processing utilizza i font che sono stati precedentemente dichiarati.
A differenza dei normali programmi di scrittura, dove troviamo il
menù a tendoina con tutti i font disponibili, Processing, essendo un
processing guida introduttiva alla programmazione visuale
49
ambiente di sviluppo permette di utilizzare qualunque font che sia
stato precedentemente impostato.
Infatti Processing utilizza solamente tipi di carattere in formato
VLW. Quando all’interno di uno Sketch sviluppato in Processing
intendiamo utilizzare un font dobbiamo prima di tutto importare il
font stesso attraverso il “Menù Tool” comando “Create Font”.
Dando questo comando si apre una finestra nella quale compare la
lista dei caratteri installati nel proprio computer. Si seleziona il
carattere e la relativa dimensione che si vuole importare e cliccando
su OK verrà automaticamente creato un file che poi potrà essere
richiamato all’interno dello Sketch.
Se ad esempio vogliamo utilizzare il font Courier nella dimensione
12 all’interno del nostro Sketch dopo avere generato il file dovremo
richiamare un file di questo nome: “Courier-12.vlw”.
Ecco uno Sketch:
size (320, 240);
background (255);
// Inizializzo la variabile
PFont carattere;
// Carico il font nello Sketch
carattere = loadFont("Courier-12.vlw");
// Stabilisco il font che sto per usare
textFont(carattere);
fill(0);
// Scrivo il testo
text("Manuale di Processing", 30, 100);
Con “PFont” viene inizializzata una variabile che conterrà il nome
del font stesso. Con “carattere = loadFont("Courier-12.vlw");”
carico nello Sketch il font che intendo utilizzare e ovvimente potrei
carirarne anche più di uno.
Poi successivamente, quando starò per utilizzare il font, dichiaro il
suo uso con “textFont(carattere);” e con “fill (0);” stabilisco che il
carattere sarà di colore nero.
Con l’istruzione “text” dichiariamo il testo che vogliamo scrivere
(potremmo in alernativa mettere il nome di una variabile String) in
seguito troviamo le coordinate X,Y dove comparirà il testo.
Nel seguente Sketch abbiamo la situazione del precedente con
l’unica differenza che attraverso l’istruzione “textSize(18);” il testo
avrà una dimensione diversa da quella importata.
processing guida introduttiva alla programmazione visuale
50
size (320, 240);
background (255);
PFont carattere;
carattere = loadFont("Courier-12.vlw");
textFont(carattere);
textSize(18);
fill(0);
text("Manuale di Processing", 30, 100);
Questa operazione di ingrandimento rappresenta un degradamento
della qualità del carattere che risulterà sgranato tanto più sarà stato
ingrandito. Infatti atttaverso l’azione di importazione del carattere
abbiamo importato delle immagini bitmap (pixel per pixel) del font.
Qualitativamente è quindi consigliabile importare i caratteri in tutte
le dimensioni che si vorranno utilizzare.
Il seguente Sketch è invece un semplice esempio di animazione di un
testo. Si tratta all’incirca della somma dello Sketch precedente e dell
Sketch utilizzato nelle pagine precedenti per animare un punto
facendolo scorrere da sinistra a destra:
void setup () {
size (320, 240);
}
int intervallo = 0;
void draw (){
background (255);
PFont carattere;
carattere = loadFont("Courier-12.vlw");
frameRate (10);
textFont(carattere);
textSize(12);
fill(0);
text("ciao a tutti", intervallo, 120);
intervallo = intervallo + 1;
}
Lavorare con le Stringhe
Processing permette di lavorare con le stringhe attraverso delle
apposite istruzioni.
Se ad esempio abbiamo la variabile “testolungo” associata ad una
string:
processing guida introduttiva alla programmazione visuale
51
String testolungo = “manuale di Processing”;
Possiamo misurare la lunghezza della stringa attraverso l’istruzione
lunghezza = testolungo.length ();
Dove lunghezza sarà una variabile di tipo “int” e in questo caso
restituirà il numero “21”, ossia la lunghezza del testo “manuale di
Processing” inclusi gli spazi tra una parola e l’altra.
Mentre con la linea di comando:
char iniziale = (testolungo.charAt(0));
Trasferisce il primo carattere (indicato con la posizione 0) della
variabile “testolungo” nella variabile iniziale. Pertanto charAt(1)
restituirà la “a” di “manuale” mentre il numero 6 ci darà la lettera
“e”. Il numero 20 la lettera “g” di “Processing”.
Attraverso l’istruzione substring (); possiamo invece prendere delle
parti di una scringa ed associarle ad un’altra variabile (oppore
stamparle...).
string pezzo = testolungo.substring(2,6);
Con questa linea di istruzione abbiamo trasferito in una nuova
variabile “pezzo” tutte le lettere comprese tra la posizione 2 e la
posizione 6 esclusa della variabile “testolungo”. In pratica abbiamo
trasferito “nual” nella variabile pezzo.
Il seguente Sketch produce una linea la cui lunghezza è inversamente
legata alla lunghezza di un testo associato ad una variabile di tipo
“String”.
size (320, 240);
String testolungo = "Manuale di
Processing" ;
// misuro la lunghezza di testolungo
int lunghezza = testolungo.length ();
// memorizzo il primo carattere
// nella variabile “iniziale”
char iniziale = (testolungo.charAt(0));
//produco una linea
//usando la lunghezza
line (lunghezza, lunghezza, 100, 100);
processing guida introduttiva alla programmazione visuale
52
Notiamo che il primo punto della linea è legato alla variabile
“lunghezza” che abbiamo utilizzato per misurale la lunghezza del
testo “manuale di Processing”.
Aggiungesto altre parole al testo “manuale di Processing” e
mandando in RUN lo Sketch vediamo che la linea tende
progressivamente ad accorciarsi.
processing guida introduttiva alla programmazione visuale
53
Quarta Parte
Grafica e Movimenti più complessi
Processing è un software specializzato per la grafica e le animazioni.
Tutte le istruzioni che abbiamo visto fino a questo punto ci hanno
permesso di comprendere i principi fondamentali della
computergrafica bidimensionale. Le forme che abbiamo disegnato
fino ad ora sono relativamente semplici.
Abbiamo visto con le curve di Bezier come sia possibile disegnare
qualunque tipo di curva utilizzando 4 paramentri.
Vediamo ora prima di tutto come animare le forme grafiche. In
realtà abbiamo già visto come sia possibile, attraverso l’uso dei
contatori e la pulizia dello schermo , animare curve e punti.
Processing ci viene incontro in queste funzionalità di animazioni
attraverso tre funzioni di animazione:
translate ();
rotate ();
scale ();
Attraverso queste tre semplici istruzioni possiamo applicare degli
effetti graficamente complessi a tutte le immagini presenti all’interno
del nostro Sketch.
Sappiamo che scrivendo queste due istruzioni:
size (320, 240);
line(10, 20, 100, 120);
otteniamo una linea che attraverso lo schermo. Attraverso
l’istruzione “translate();” abbiamo la possibilità di traslare la linea
sulle coordinate X e Y.
Infatti se scriviamo:
size (320, 240);
translate(100, 0);
line(10, 20, 100, 120);
succede che la linea, a differenza del precedente Sketch, avrà delle
cordinate traslate di 100 pixel sull’asse delle X. Le nuove coordinate
della linea saranno: (110, 20, 200, 120). I due valori X dei due punti
sono stati incrementati di 100 pixel.
processing guida introduttiva alla programmazione visuale
54
Ecco il risultato aritmetico dell’istruzione:
line (10 + 100, 20 + 0, 100 + 100, 120 + 0);
Ovviamente possiamo traslare sia le coordinate X che le Y, ecco un
esempio:
size (320, 240);
translate(100, 25);
line(10, 20, 100, 120);
La linea disegnata sullo schermo avrà le seguenti coordinate:
line (110, 45, 200, 145);
L’istruzione traslate è attiva per tutte le forme grafiche che appaino
successivamente ad essa. Pertanto se tracciamo due linee dopo
l’istruzione traslate otteniamo che tutte e due le linee saranno
traslate.
size (320, 240);
translate(100, 25);
line (10, 20, 100, 120);
line (20, 40, 200, 100);
Mandando in RUN lo Sketch vediamo che sia la prima che la
seconda linea risultano traslate. Inoltre le traslazioni si sommano,
pertanto se vogliamo ulteriormente traslare una linea dopo una
prima traslazione sarà sufficiente inserire la nuova traslazione.
size (320, 240);
translate(100, 25);
line (10, 20, 100, 120);
translate(80, 15);
line (20, 40, 200, 100);
La seconda linea del precedente Sketch è traslata nelle sue
coordinate di 180 (100+80) pixel sull’asse “X” e 40 pixel sull’asse
“Y” (25+15). Mentre la prima linea risulta traslata solamente dei
valori del primo comando traslate.
processing guida introduttiva alla programmazione visuale
55
Per ripristinare le condizioni originarie è sufficiente mettere in
negativo i valori di traslate. Nel sequente Sketch le coordinate della
seconda linea sono “normali”.
size (320, 240);
translate(100, 25);
line (10, 20, 100, 120);
translate(-100, -25);
line (20, 40, 200, 100);
Poichè la seconda istruzione “traslate” sottrae esattamente i valori
della prima istruzione, la seconda linea avrà le coordinate:
line (20, 40, 200, 100);
Proprio come indicato nello Sketch stesso.
Rotazione
I principi della traslazione valgono anche nel caso della rotazione.
Essi quindi sono validi finchè non intervenga un nuovo valore che si
somma al precedente.
Per capire l’unità di misura dela rotazione dobbiamo capire il
concetto di radiante. Normalmente misuriamo i giri in gradi, quindi
un giro completo è di 360 gradi mentre un giro di 180 gradi è mezzo
giro. Una ruotazione ad angolo retto è una ruotazione di 90 gradi.
I radianti sono legati alla costante matematica detta “Pi greco” “PI”
o “π”. Il pi greco misura il rapporto tra una qualunque circonferenza
di un cerchio e il suo relativo diametro. Questo rapporto è costante e
viene sintetizzato in 3.14 anche se i decimali dopo la virgola sono
infiniti.
La corrispondenza tra i gradi e i radianti è molto semplice:
- due radianti (2 * π) sono 360 gradi
- un radiante (π) è 180 gradi
- mezzo radiante (π/2) è 90 gradi
In processing π si scrive PI. Il seguente Sketch mostra la ruotazione
di una stessa linea di 90 gradi:
size (240, 240);
line(0, 0, 100, 0);
rotate(PI/2);
line(0, 0, 100, 0);
processing guida introduttiva alla programmazione visuale
56
Mandando in RUN lo Sketch lediamo una linea in alto orizzontale
(la prima linea dello Sketch) e una seconda linea verticale che è la
seconda linea dello Sketch. La seconda linea ha subito quindi una
rotazione di 90 gradi in senso orario.
Le dimensione dello schermo questa volta sono state impostate a
(240, 240) al fine di facilitare la comprensione dei gradi.
Osserviamo infatti una rotazione di 45 gradi:
size (240, 240);
line(0, 0, 240, 0);
rotate(PI/4);
line(0, 0, 240, 0);
Vediamo che la seconda linea in questo caso è ruotata di 45 gradi e
grazie al fatto che la finestra è quadrata possiamo osservare che essa
traccia una pate della diagonale della finestra stessa.
Di seguito vediamo tre linee. La prima non subisce alcuna
ruotazione mentre la seconda subisce una ruotazione di 45 gradi
(PI/4) e la terza ruota di 90 gradi (PI/4 + PI/4 = PI/2).
size (240, 240);
line(0, 0, 240, 0);
rotate(PI/4);
line(0, 0, 240, 0);
rotate(PI/4);
line(0, 0, 240, 0);
La funzione di ruotazione funziona quindi come la funzione di
traslazione. Per eliminare il suo effetto è sufficiente riproporre il
valore in negativo:
size (240, 240);
line(0, 0, 240, 0);
rotate(PI/4);
line(0, 0, 240, 0);
rotate(- PI/4);
strokeWeight (5);
line(0, 0, 200, 0);
In questo caso la terza linea sembra scomparire mentre in realtà essa
è perfettamente sovrapposta alla prima linea. Per questo motivo ho
processing guida introduttiva alla programmazione visuale
57
aumentato lo spessore della linea “strokeWeight (5);” inoltre ho
leggermente accorciato la lua lunghezza in modo che si possa
cogliere anche la prima linea.
Infine per comprendere completamente il tipo di ruotazione che
avviene mandiamo in RUN il seguente Sketch
size (240, 240);
ellipse (100, 0, 20, 20);
rotate(PI/4);
ellipse (100, 0, 20, 20);
Vediamo anche in questo caso che il cerchio si sposta. Mentre se il
cerchio ruotasse su se stesso non dovremmo vedere alcuno
spostamento. In effetti con il comando rotate così come con il
comando translate ciò che ruota non è l’oggetto bensì la finestra con
tutto ciò che è disegnato al suo interno. Questa ruotazione fa perno
sulla coordinata (0,0) dello schermo.
Scala
Per ingrandire o rimpiccolire un oggetto si utilizza l’istruzione scale
();.
Il seguente Sketch mostra due cerchi dove il secondo cerchio è stato
raddoppiato nelle sue dimensioni:
size (240, 240);
ellipse (100, 100, 20, 20);
scale (2);
ellipse (100, 100, 20, 20);
Le coordinate del cerchio cambiano proprio perchè è la finestra che
si raddoppia nella sua dimensione con tutti i suoi contenuti.
Il seguente Sketch mostra tre cerchi. Il terzo cerchio ha le stesse
proporzioni del primo ma ho modificato il riempimento e
ridimensionato il raggio.
size (240, 240);
ellipse (100, 100, 20, 20);
scale (2);
ellipse (100, 100, 20, 20);
scale (0.5);
fill (100,20);
processing guida introduttiva alla programmazione visuale
58
ellipse (100, 100, 10, 10);
Vediamo che attraverso l’istruzione “scale (0.5);” è stato diviso per
due il precedente rapporto di ingrandimento “scale(2)”. In questo
modo il rapporto finale è 0.5*2 cioè 1.
Quest’ultimo Sketch ci mostra tre cerchio scalati ogni volta per due.
Il terzo cerchio sarà quindi 4 volte (2*2) più grande del primo.
size (240, 240);
ellipse (50, 50, 20, 20);
scale (2);
ellipse (50, 50, 20, 20);
scale (2);
ellipse (50, 50, 20, 20);
Da notare che anche la distanza tra il secondo e il terzo cerchio è
doppia rispetto alla distanza tra il primo e il secondo cerchio.
Infine notiamo che le tre funzionalità di modifica delle forme
grafiche possono ovviamente essere utilizzate in modo combinato.
size (240, 240);
ellipse (50, 50, 20, 20);
scale (2);
ellipse (50, 50, 20, 20);
translate (20, 0);
ellipse (50, 50, 20, 20);
Nel precedente Sketch i cerchio risulterà traslato di 20 pixel sull’asse
delle X e ingrandito di due volte. Il secondo cerchio ha invece subito
solamente l’ingrandimento ma non la traslazione.
processing guida introduttiva alla programmazione visuale
59
Quinta parte
Arduino
Arduino è una piattaforma open source per lo sviluppo e la
progettazione di oggetti interattivi.
Lo scopo principale di questa scheda è quella di dare la possibilità a
sviluppatori e artisti di progettare prototipi letteralmente “giocando”
con l’elettronica e sperimentando con sensori, attuatori e controller
elettronici.
Questa particolare ricerca nell’interazione tra il calcolatore e il
mondo fisico è nota come “Physical Computing” ed era fino a pochi
anni fa una disciplina conosciuta e utilizzata solo in campo
ingegneristico, che richiedeva una conoscenza avanzata
dell’elettrotecnica e del software.
Questo livello di complessità ha tenuto per anni lontani gli ideatori,
gli obbisti e gli artisti dalle infinite possibilità che l’elettronica può
aprire nel mondo del design e dell’arte in generale.
Lo scopo degli sviluppatori di Arduino è quello di fornire uno
strumento semplice che permetta a chiunque di iniziare a costruire
progetti interattivi in modo immediato ed economico.
Grazie a questa semplicità di utilizzo e alla crescente diffusione, oggi
Arduino oltre a risolvere numerosi problemi nello sviluppo e nella
realizzazione di oggetti interattivi, è alla base di una nuova filosofia
che cresce e si alimenta dal mondo dell’open source e dalla
condivisione di conoscenze tipica della rete.
Nel mondo anglosassone questo “modo di procedere” nello
sviluppo è noto come “Tinkering”, una forma di deriva creativa
guidata dall’immaginazione e dalla curiosità.
Mentre il percorso di sviluppo ingegneristico classico presuppone
una progettazione che procede in modo razionale dal punto A al
punto B, il Tinkering presuppone il perdersi in questo percorso e
scoprire un nuovo punto C.
Tinkering significa in pratica trovare risultati curiosi provando e
sbagliando procedimenti ignoti.
processing guida introduttiva alla programmazione visuale
60
Costruire senza le istruzioni, giocando con i fallimenti, non
preoccupandosi del modo giusto o sbagliato di fare le cose.
Uno dei modi migliori di utilizzare questo processo creativo è
riutilizzare tecnologie esistenti, smontare vecchi apparecchi
elettronici e usarne parti interessanti sfruttandole per utilizzi lontani
da quelli per cui erano state progettate.
Questo approccio spontaneo e casuale è alla base di alcune nuove
forme d’arte come il Circuit Bending: un genere musicale suonato
con vecchi strumenti giocattolo elettronici, smontati e modificati per
creare suoni completamente diversi da quelli pensati dal costruttore
originario.
Arduino insomma rappresenta oggi una nuova ottica con cui
guardare la tencologia che ci circonda, sviluppare nuove funzioni per
strumenti vecchi ed esplorare nuove possibilità senza il bisogno di
perdersi in anni di studi ma semplicemente giocando con ciò che già
abbiamo a portata di mano sfruttando l’istinto di ogni bambino...
smontare i giocattoli per vedere cosa c’è dentro.
L’Hardware:
Arduino è una scheda composta principalmente da un processore e
una serie di ingressi e uscite sia digitali che analogici, alimentabile sia
via USB che tramite un alimentatore esterno.
processing guida introduttiva alla programmazione visuale
61
Il Software:
Il processore di Arduino è programmabile attraverso un ambiente di
sviluppo(IDE) basato su Processing.
Tutto il software necessario all’utilizzo di Arduino oltre a svariati
esempi di codice è scaricabile gratuitamente dal sito www.arduino.cc
Una volta scritto il programma nell’editor principale (proprio come
un programma in Processing) va controllata la sua correttezza,
premendo verify, se il codice è scritto correttamente apparirà il
messaggio Done compiling, a questo punto é possibile caricare il
programma nel processore di Arduino.
Premendo il bottone reset su Arduino si hanno 6 secondi per
premere Upload to I/O board nella parte alte dell’IDE.
Questo procedimento invia il programma alla scheda, lo salva nella
sua memoria e lo esegue automaticamente.
processing guida introduttiva alla programmazione visuale
62
La BreadBoard
Prima che il vostro circuito funzioni perfettamente ci sarà bisogno di
vari tentativi e saldare diversi tentativi su una piastra è un lavoro
lungo e dispendioso.
L’equivalente elettronico dello schizzo iniziale di un progetto fatto
su un foglio di carta è la BreadBoard.
Si tratta in pratica di una piastra di plastica piena di fori ognuno dei
quali contiene un contatto.
Quando si mette un componente in uno di questi fori si crea un
contatto elettrico con tutti gli altri fori della stessa colonna verticale.
Le due coppie di linee di fori in alto e in basso della Breadboard
(solitamente colorate di rosso e blu e con il segno+ e -) sono invece
collegate in orizzontale e sono usate per portare l’alimentazione in
tutta la piastra.
processing guida introduttiva alla programmazione visuale
63
Processing  -guida_introduttiva_alla_pro
Processing  -guida_introduttiva_alla_pro
Processing  -guida_introduttiva_alla_pro
Processing  -guida_introduttiva_alla_pro
Processing  -guida_introduttiva_alla_pro
Processing  -guida_introduttiva_alla_pro

More Related Content

Similar to Processing -guida_introduttiva_alla_pro

Ribesdesign interfacce
Ribesdesign interfacceRibesdesign interfacce
Ribesdesign interfacceRibesdesign
 
Guida Di Stile:SdcExpert@Work
Guida Di Stile:SdcExpert@WorkGuida Di Stile:SdcExpert@Work
Guida Di Stile:SdcExpert@WorkRoberta Sanzani
 
14 - Web designer vs Web developer ...
14 - Web designer vs Web developer ... 14 - Web designer vs Web developer ...
14 - Web designer vs Web developer ... Giuseppe Vizzari
 
Linux Nelle Aziende Installfest2007
Linux Nelle Aziende Installfest2007Linux Nelle Aziende Installfest2007
Linux Nelle Aziende Installfest2007jekil
 
Cosa è un servizio digitale?
Cosa è un servizio digitale?Cosa è un servizio digitale?
Cosa è un servizio digitale?Metooo
 
Il software applicativo
Il software applicativoIl software applicativo
Il software applicativoalyssandrea
 
Profilazione di applicazioni PHP con XHProf.
Profilazione di applicazioni PHP con XHProf.Profilazione di applicazioni PHP con XHProf.
Profilazione di applicazioni PHP con XHProf.Filippo Matteo Riggio
 
I software william e alyssa
I software william e alyssaI software william e alyssa
I software william e alyssaWILLIII
 
Generazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGenerazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGiacomoZorzin
 
Flavio ATZENI - SMAU 2014
Flavio ATZENI - SMAU 2014Flavio ATZENI - SMAU 2014
Flavio ATZENI - SMAU 2014Paradisi63
 
Studio e sviluppo di un’interfaccia per applicazione WEB 2.0
Studio e sviluppo di un’interfaccia per applicazione WEB 2.0Studio e sviluppo di un’interfaccia per applicazione WEB 2.0
Studio e sviluppo di un’interfaccia per applicazione WEB 2.0NobelMusic
 
Open source un'opportunità di business
Open source un'opportunità di businessOpen source un'opportunità di business
Open source un'opportunità di businessRoberto Falla
 
Verifica finale
Verifica finaleVerifica finale
Verifica finalegianter62
 
Verifica finale
Verifica finaleVerifica finale
Verifica finalegianter62
 
IBM Softwareland 2008 - Rational
IBM Softwareland 2008 - RationalIBM Softwareland 2008 - Rational
IBM Softwareland 2008 - Rationalfedericobotti
 
Web designer vs Web developer
Web designer vs Web developerWeb designer vs Web developer
Web designer vs Web developerGiuseppe Vizzari
 

Similar to Processing -guida_introduttiva_alla_pro (20)

Ribesdesign interfacce
Ribesdesign interfacceRibesdesign interfacce
Ribesdesign interfacce
 
Software 1
Software 1Software 1
Software 1
 
Strumenticollaborativiopen
StrumenticollaborativiopenStrumenticollaborativiopen
Strumenticollaborativiopen
 
Guida Di Stile:SdcExpert@Work
Guida Di Stile:SdcExpert@WorkGuida Di Stile:SdcExpert@Work
Guida Di Stile:SdcExpert@Work
 
Software 2
Software 2Software 2
Software 2
 
14 - Web designer vs Web developer ...
14 - Web designer vs Web developer ... 14 - Web designer vs Web developer ...
14 - Web designer vs Web developer ...
 
Linux Nelle Aziende Installfest2007
Linux Nelle Aziende Installfest2007Linux Nelle Aziende Installfest2007
Linux Nelle Aziende Installfest2007
 
Software
SoftwareSoftware
Software
 
Cosa è un servizio digitale?
Cosa è un servizio digitale?Cosa è un servizio digitale?
Cosa è un servizio digitale?
 
Il software applicativo
Il software applicativoIl software applicativo
Il software applicativo
 
Profilazione di applicazioni PHP con XHProf.
Profilazione di applicazioni PHP con XHProf.Profilazione di applicazioni PHP con XHProf.
Profilazione di applicazioni PHP con XHProf.
 
I software william e alyssa
I software william e alyssaI software william e alyssa
I software william e alyssa
 
Generazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGenerazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptx
 
Flavio ATZENI - SMAU 2014
Flavio ATZENI - SMAU 2014Flavio ATZENI - SMAU 2014
Flavio ATZENI - SMAU 2014
 
Studio e sviluppo di un’interfaccia per applicazione WEB 2.0
Studio e sviluppo di un’interfaccia per applicazione WEB 2.0Studio e sviluppo di un’interfaccia per applicazione WEB 2.0
Studio e sviluppo di un’interfaccia per applicazione WEB 2.0
 
Open source un'opportunità di business
Open source un'opportunità di businessOpen source un'opportunità di business
Open source un'opportunità di business
 
Verifica finale
Verifica finaleVerifica finale
Verifica finale
 
Verifica finale
Verifica finaleVerifica finale
Verifica finale
 
IBM Softwareland 2008 - Rational
IBM Softwareland 2008 - RationalIBM Softwareland 2008 - Rational
IBM Softwareland 2008 - Rational
 
Web designer vs Web developer
Web designer vs Web developerWeb designer vs Web developer
Web designer vs Web developer
 

Recently uploaded

IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla Cresima
IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla CresimaIL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla Cresima
IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla CresimaRafael Figueredo
 
San Giorgio e la leggenda del drago.pptx
San Giorgio e la leggenda del drago.pptxSan Giorgio e la leggenda del drago.pptx
San Giorgio e la leggenda del drago.pptxMartin M Flynn
 
Esperimenti_laboratorio di fisica per la scuola superiore
Esperimenti_laboratorio di fisica per la scuola superioreEsperimenti_laboratorio di fisica per la scuola superiore
Esperimenti_laboratorio di fisica per la scuola superiorevaleriodinoia35
 
XIII Lezione - Arabo G.Rammo @ Libera Accademia Romana
XIII Lezione - Arabo G.Rammo @ Libera Accademia RomanaXIII Lezione - Arabo G.Rammo @ Libera Accademia Romana
XIII Lezione - Arabo G.Rammo @ Libera Accademia RomanaStefano Lariccia
 
Corso di digitalizzazione e reti per segretario amministrativo
Corso di digitalizzazione e reti per segretario amministrativoCorso di digitalizzazione e reti per segretario amministrativo
Corso di digitalizzazione e reti per segretario amministrativovaleriodinoia35
 
CON OCCHI DIVERSI - catechesi per candidati alla Cresima
CON OCCHI DIVERSI - catechesi per candidati alla CresimaCON OCCHI DIVERSI - catechesi per candidati alla Cresima
CON OCCHI DIVERSI - catechesi per candidati alla CresimaRafael Figueredo
 
XI Lezione - Arabo LAR Giath Rammo @ Libera Accademia Romana
XI Lezione - Arabo LAR Giath Rammo @ Libera Accademia RomanaXI Lezione - Arabo LAR Giath Rammo @ Libera Accademia Romana
XI Lezione - Arabo LAR Giath Rammo @ Libera Accademia RomanaStefano Lariccia
 
RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.
RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.
RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.giuliofiorerm
 
lezione di fisica_I moti nel piano_Amaldi
lezione di fisica_I moti nel piano_Amaldilezione di fisica_I moti nel piano_Amaldi
lezione di fisica_I moti nel piano_Amaldivaleriodinoia35
 

Recently uploaded (9)

IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla Cresima
IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla CresimaIL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla Cresima
IL CHIAMATO ALLA CONVERSIONE - catechesi per candidati alla Cresima
 
San Giorgio e la leggenda del drago.pptx
San Giorgio e la leggenda del drago.pptxSan Giorgio e la leggenda del drago.pptx
San Giorgio e la leggenda del drago.pptx
 
Esperimenti_laboratorio di fisica per la scuola superiore
Esperimenti_laboratorio di fisica per la scuola superioreEsperimenti_laboratorio di fisica per la scuola superiore
Esperimenti_laboratorio di fisica per la scuola superiore
 
XIII Lezione - Arabo G.Rammo @ Libera Accademia Romana
XIII Lezione - Arabo G.Rammo @ Libera Accademia RomanaXIII Lezione - Arabo G.Rammo @ Libera Accademia Romana
XIII Lezione - Arabo G.Rammo @ Libera Accademia Romana
 
Corso di digitalizzazione e reti per segretario amministrativo
Corso di digitalizzazione e reti per segretario amministrativoCorso di digitalizzazione e reti per segretario amministrativo
Corso di digitalizzazione e reti per segretario amministrativo
 
CON OCCHI DIVERSI - catechesi per candidati alla Cresima
CON OCCHI DIVERSI - catechesi per candidati alla CresimaCON OCCHI DIVERSI - catechesi per candidati alla Cresima
CON OCCHI DIVERSI - catechesi per candidati alla Cresima
 
XI Lezione - Arabo LAR Giath Rammo @ Libera Accademia Romana
XI Lezione - Arabo LAR Giath Rammo @ Libera Accademia RomanaXI Lezione - Arabo LAR Giath Rammo @ Libera Accademia Romana
XI Lezione - Arabo LAR Giath Rammo @ Libera Accademia Romana
 
RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.
RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.
RICERCA_SUGLI ANFIBI PER LA PRIMA MEDIA.
 
lezione di fisica_I moti nel piano_Amaldi
lezione di fisica_I moti nel piano_Amaldilezione di fisica_I moti nel piano_Amaldi
lezione di fisica_I moti nel piano_Amaldi
 

Processing -guida_introduttiva_alla_pro

  • 1. processing guida introduttiva alla programmazione visuale 1 processing guida introduttiva alla programmazione visuale alberto cecchi valerio belloni ...
  • 2. indice: prima parte: seconda parte: terza parte: quarta parte: quinta parte: This work is licensed under the Creative Commons Attribution- Noncommercial-Share Alike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc- sa/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. processing guida introduttiva alla programmazione visuale 2 p.3 p.34 p.48 p.54 p.60
  • 3. Processing Programmare per l’arte Prima Parte Possiamo dire che Processing è un software grafico che si occupa di Immagini, Forme, Movimenti, Suoni e Interazioni. Processing è allo stesso tempo un linguaggio di programmazione, un ambiente di sviluppo nonché un metodo di insegnamento della programmazione. Processing è stato inventato da Casey Reas e Ben Fry al fine di insegnare agli studenti nel settore dell’arte e della grafica la programmazione software. Oggi Processing è utilizzato da studenti, artisti, designers e ricercatori per imparare, sperimentare e produrre. Processing rappresenta in pieno il proverbio di Confucio: “se ascolto dimentico, se vedo ricordo, se faccio capisco” Processing, in quanto linguaggio di programmazione, è un linguaggio testuale (si scrivono le istruzioni) pensato per produrre e modificare immagini. Processing è il giusto compromesso tra semplicità (nell’uso) e complessita dei risultati che si possono raggiungere. Sono sufficienti pochi minuti di corso affinchè uno studente possa scrivere le prime righe di codice ed osservare dei risultati. Utenti avanzati possono invece realizzare progetti anche molto complessi scrivendo direttamente delle librerie che possono anche migliorare ed aumentare le funzionalità del software stesso. I lavori fatti in Processing possono essere facilmente esportati nel web e questo aspetto ha facilitato la distribuzione del software e della sua conoscenza. Il sito ufficiale di Processing è www.processing.org, all’interno del sito è presente anche un forum con migliaia di iscritti che discutono assiduamente riguardo le problematiche tecniche e creative. Processing facilita l’insegnamento della grafica digitale, delle tecniche di interazione come ad esempio disegno vettoriale e raster, image processing guida introduttiva alla programmazione visuale 3
  • 4. processing, gestione degli eventi del mouse e della tastiera e comunicazione nelle reti di computer. Le librerie estendono le funzionalità di base anche alla generazione dei suoni, alla comunicazione dei dati (input/output) alle funzionalità tridimensionali ed esportazioni file in vari formati. Il linguaggio Processing non è molto diverso da tanti altri linguaggi di programmazione. Processing è stato progettato raffinando e rivedendo questi linguaggi che lo hanno preceduto. Questo aspetto è molto importante, infatti possiamo vedere Processing come uno strumento per avvicinarsi alla programmazione. Chi impara a programmare in Processing avrà il futuro molto facilitato qualora volesse imparare a programmare anche in altri linguaggi. L’aspetto principale che differenzia Processing da altri linguaggi di programmazione riguarda la sua versatilità per tutto ciò che è legato alla grafica, al disegno, all’animazione e alle interazioni live. Installare e Aprire Processing Processing è appunto Open Source e completamente gratuito. Per Scaricarlo è sufficiente andare all’indirizzo www.processing.org/ download dove si trovano le versioni per Linux, OSX e Windows. L’ambiente di sviluppo di Processing (Processing Development Environment PDE) è composto da un semplice editor testuale dove vengono scritte le istruzioni. PDE è anche l’estensione dei file di lavoro prodotti in Processing. Poi troviamo un’area messaggi, una console testuale e una toolbar dalla quale possono essere effettuate le operazioni più comuni (nuovo, apri, salva, esporta…). Sempre nella Toolbar in alto sono presenti i due tipici pulsanti degli ambienti di programmazione (Stop e Run). Ecco la lista completa dei pulsanti presenti nella Toolbar: RUN STOP NEW OPEN SAVE EXPORT processing guida introduttiva alla programmazione visuale 4
  • 5. Quando si lancia un programma (Run) il risultato compare in una finestra che si apre automaticamente (display window). Ogni programma scritto con Processing (attraverso l’editor testuale) si chiama Sketch. All’interno dell’editor testuale sono presenti le due tipiche funzionalità Taglia e Incolla (Cut and Paste) e Cerca e Sostituisci (Search and Replace). L’area messaggi, in basso ci dice ad esempio se una volta lanciato il programma ci sono errori. In pratica l’area messaggi è il mezzo che Processing usa per comunicare con noi, scrivendoci in quell’area qualunque tipo di messaggio riguardo il suo comportamento (ad esempio se si scrive uno Sketch errato sarà l’area messaggi ad avvertirci). L’area della conosole testuale (sotto l’area messaggi) ci scrive dei messaggi in forma più estesa e dettagliata della message window). Questa area ha anche la funzione di controllo durante le operazioni di programmazione. Ad esempio quando si vuole controllare una fare intermedia della programmazione, possiamo far comparire in questa finestra i dati desiderati (più avanti sarà tutto più chiaro). I menu di Processing sono solo 6: Processing File Edit Sketch Tools Help Questa breve lista dei menù all’interno dei quali troviamo pochi comandi, rende l’idea della semplicità dell’ambiente di sviluppo Processing. Vedremo i comandi all’interno dei menù più avanti. Quando si crea un nuovo Sketch (programma) Processing crea automaticamente anche una specifica cartella che avrà lo stesso nome dello sketch (come spiegato prima il file dove è scritto il programma ha l’estensione .pde). Processing è un ambiente in grado di gestire file multimediali pertanto se all’interno del nostro progetto per esempio aggiungiamo un suono o un’immagine questi file andranno a collocarsi automaticamente dentro la cartella data, all’interno della cartella dello Sketch. Processing permette di lavorare secondo la logica “drag and drop” pertanto per aggiungere un’immagine al nostro programma è sufficiente prendere il file e trascinarlo sopra l’editor testuale dove stiamo scrivendo il nostro Sketch. processing guida introduttiva alla programmazione visuale 5
  • 6. La cartella dello Sketch che a sua volta conterrà anche la cartella data con tutti i file multimediali aggiunti si troverà in una directory del computer che possiamo decidere dal menù File/Preferences. Programmare in Processing Abbiamo detto che programmare in Processing è molto semplice pertanto il modo migliore per capire questo concetto è iniziare a scrivere qualche semplice programma cercando di comprenderne il senso. //Creiamo una finestra 320 x 240 pixel// size(320, 240); background(255); Abbiamo scritto tre righe nella finestra testuale dell’ambiente di sviluppo di Processing. La prima riga potrebbe sembrare semplice e tutti i programmatori giovani o inesperti o egoisti o masochisti tendono a trascurare questo tipo di istruzione che invece è determinante. Ogni volta che scriviamo un programma dobbiamo aggiungere dei commenti che possano essere letti dai programmatori ma che non vengano interpretati come istruzioni dal programma stesso. I commenti sono importanti perchè attraverso i commenti il programmatore dichiara le operazioni che compie in modo che potrà rileggerli in futuro oppure in modo che altri programmatori che apriranno il programma leggendo i commenti possano capire come ha ragionato il programmatore precedente. Commentare un programma significa comunicare con se stessi (nel futuro) e con gli altri. Non commentare un programma significa non comunicare ne con se stessi (quando un anno dopo aprirete un programma fatto e non commentato non ricorderete quali ragionaventi avrete fatto e vi dispererete) ne con altre persone alle quali per lavoro o per divertimento volete lasciare in eredità il vostro lavoro. Un programma non commentato è spazzatura. Questo aspetto così centrale della programmazione risulta ancor più centrale quando ci riferiamo ad un programma Open Source come Processing. Processing non costa nulla perchè delle persone buone d’animo hanno lavorato a lungo e hanno deciso di larsciarci in eredità gratuita il loro lavoro. Un programmatore che non scrive i commenti sui programmi realizzati in processing contravviene alla processing guida introduttiva alla programmazione visuale 6
  • 7. filosofia Open Source perchè i suoi programmi saranno difficilmente interpretabili da altri programmatori. La stesso giudizio però vale anche per i programmatori che lavorano in ambiti commerciali. Un programmatore che non commenta i propri software danneggia economicamente il suo datore di lavoro e tutto l’ambiente nel quale lavora. Torniamo quindi alla nostra prima riga di programma scritta in Processing //Creiamo una finestra 320 x 240 pixel// I due slash “//” indicano esattamente l’inizio e la fine di un commento del programmatore. Questo commento è molto semplice agli occhi di un programmatore esperto potrebbe sempbrare inutile ma in realtà quanto più diffusamnte è documentato un software tanto più facile sarà la sua lettura e correzione in futuro. Per scrivere dei commenti che siano più lunghi di una riga Processing ci permette di utilizzare anche la seguente forma: /* I commenti sono molto importanti possiamo scriverli anche in più righe il software non interpreta queste istruzioni */ Vediamo invece ora la prima istruzione (o funzione) vera e propria: size(320, 240); Possiamo notare in questa istruzione tre elementi importanti: - Il comando “size” - I parametri (320, 240) - Il simbolo che chiude l’istruzione “;” Il comando “size” stabilisce che deve essere creata una finestra. Questa è la tipica istruzione con cui si inizia a programmare in Processing. Con “size” si stabiliscono le dimensioni della finestra sulla quale poi compariranno i risultati del nostro programma. Le dimensioni che abbiamo stabilito in questo caso sono 320 pixel in larghezza (asse X) e 240 pixel in altezza (asse Y). Con “;” invece diciamo a Processing è terminata l’istruzione. Da notare la seguente istruzione: processing guida introduttiva alla programmazione visuale 7
  • 8. //size(320, 240); Poichè la riga inizia con “//” Processing interpreterà tutto ciò che segue come un commento e quindi quando si lancerà il programma non verrà effettuata nessuna azione. A volte i programmatori disordinati tendono a commentare molto le istruzioni durante il processo produttivo. Questa operazione se non documentata è un operazione che genera solo confusione. Pertanto quando si commenta un’istruzione è bene spiegare, attraverso un ulteriore commento il motivo per il quale sono presenti delle istruzioni commentate. Rispetto ai paramentri è importante notare che ad esempio nel caso di “size” debbono essere 2 e la loro posizione è obbligatoria. Al primo posto si mette il valore delle X e al secondo posto (dopo la virgola) si mette il valore delle Y. Infine da notare un aspetto molto importante della programmazione, la convenzione di chiudere l’istruzione con “;” potrebbe sembrare inutile e noiosa. Potrebbe anche essere così, ma comunque è dobbiamo capire che qualora non mettessimo quel dettaglio “;” il nostro programma non funzionerà. I linguaggi di programmazione usano una sintassi molto più rigida della sintassi che si usa quando si parla o quando si scrive una mail. Quando scriviamo una mail ad un amico e ci dimentichiamo una virgola nel contenuto del nostro messaggio esso arriverà a destinazione uguamente. Se invece facciamo un errore quando scriviamo l’indirizzo mail il messaggio non arriverà mai al destinatario. Scrivere un’istruzione in Processing è come scrivere un indirizzo mail, se non metti la chiocciola o sbagli anche solo un puntino non funzionerà nulla. Gli aspetti formali della programmazione sono importanti e non possono essere tralasciati. Un altro aspetto formale che non possiamo tralasciare in Processing è che i comandi sono “case sensitive”. “Size” e “size”non sono la stessa cosa, il comando “size” deve essere scritto con tutte le lettere minuscole, se non lo facciamo Processing non interpreta il comando. “Size” per Processing non significa nulla. Torniamo ora alla terza riga del nostro breve programma: background(255); processing guida introduttiva alla programmazione visuale 8
  • 9. Possiamo facilmente distiguere il comando “background” il parametro tra parentesi e il termine della riga di istruzione “;”. Il comando specifico “background” indica a Processing il colore che dovrà avere lo sfondo della finestra che abbiamo appena creato. 255 indica il colore bianco. Una volta terminato di scrivere il nostro programma in tre righe lo potremo lanciare cliccando sul pulsante RUN. Potremo interrompere l’esecuzione del nostro programma cliccando sul pulsante STOP. Numeri e Variabili Abbiamo creato il nostro primo breve programma in Processing. Abbiamo compreso alcuni principi base della programmazione. Questi principi sono pressochè universali nella programmazione e comprenderli in processing ci permetterà poi di applicarli a praticamente qualunque altro linguaggio di programmazione. Nel nostro primo programma abbiamo visto che i comandi possono avere dei parametri e che questi parametri si esprimono in numeri. Nella programmazione è normale però esprimere i numeri anche attraverso delle variabili. Queste due espressioni producono lo stesso risultato: //senza variabili background(0); //con variabili int X = 0; background (X); Nel secondo caso abbiamo fatto due operazioni. Con la prima operazione abbiamo detto al programma di attivare l’uso di una variabile che abbiamo chiamato “X” e abbiamo assegnato un valore a questa variabile “0”. Il risultato è che “background” avrà un valore pari a zero, proprio come nel primo esempio. Le variabili sono molto utili nella programmazione proprio perchè sono “variabili” e quindi il loro valore può cambiare in base a degli processing guida introduttiva alla programmazione visuale 9
  • 10. eventi , oppure possono cambiare in base a delle operazioni matematiche. Le variabili sono molto utili anche perchè memorizzano dei valori e permettono di riutilizzarli quando serviranno in futuro. Esistono diversi tipi di variabili; nel nostro esempio “int” indica una variabile che può assumere un valore numerico intero (senza valori dopo la virgola). “float” è un altro tipo di variabile numerica che può invece contenere anche valori dopo la “virgola”. Importante: come in quasi tutti i linguaggi legati all’informatica la virgola che noi utilizziamo nei numeri per indicare i valori decimali, deve essere sostituita dal punto “.”. Nei linguaggi di programmazione 10.5 equivale al 10,5 nella notazione che utilizziamo in Italia. Da notare che non è possibile fare operazioni matematiche mescolando due variabili di tipo diverso (una “int” e l’altra “float”). Nel linguaggio comune della programmazione l’istruzione: int X = 0; viene detta inizializzazione o dichiarazione di una variabile. Questo tipo di istruzioni generalmente vengono messe all’inizio dei programmi e comunque debbono essere posizionate sempre prima che si utilizzi la variabile stessa. La seguente sequenza non funzionerebbe: background (X); int X = 10; Se vogliamo utilizzare la variabile “X” prima la dobbiamo inizializzare “int X = 10;”. Una volta che la variabile è stata inizializzata è possibile utilizzarla tutte le volte che si desidera. Inoltre dopo l’inizializzazione la variabile può essere “manipolata”. Nell’esempio seguente osserviamo che: int X = 10; X = 6; background (X); la variabile “X” è stata prima inizializzata poi successivamente è stato assegnato un nuovo valore alla variabile “X = 6;”. processing guida introduttiva alla programmazione visuale 10
  • 11. Pertanto il valore finale di “background (X);” sarà 6. Ovviamente per brevità sarebbe stato più intelligente scrivere: int X = 6; background (X); il risultato sarebbe stato identico. Il nome delle variabili Abbiamo visto quindi che le variabili hanno un nome. Ho utilizzato “x” e come primo passagio potrebbe essere anche corretto ma quandi si scrive un programma più complesso è invece consigliabile dare un nome “sensato” alle variabili. Il lungo discorso che ho fatto nelle pagine precedenti riguardo i commenti vale anche per le variabili. Ipotizziamo ad esempio di voler disegnare un cerchio attraverso un programma e ipotizziamo che questo cerchio cambierà di dimensione durante l’esecuizone del programma stesso. Potremmo assegnare a questa variabile semplicemente una lettera “X” oppure “C”, ma se immaginiamo che il nostro programma sarà abbastanza complesso allora sarà sicuramente meglio utilizzare un nome della variabile più esteso. Possiamo chiamare la variabile che gestirà il nostro cerchio ad esempio “cerchio”. In questo modo quando riapriremo il programma in futuro oppure qualcun’altro aprirà il nostro programma il nome della variabile permetterà facilmente di comprendere di che variabile si tratta e per che cosa viene utilizzata. Pertanto quando dichiarerò la mia variabile all’inizio del programma scriverò int cerchio = 10; anzichè int X = 10; Il termine cerchio ci aiuterà molto in futuro quando il nostro programma andrà progressivamente coplicandosi. Ma in realtà un buon programmatore dovrebbe precedere la dichiarazione della variabile con un commento che spiega a cosa serve quella variabile. Ad esempio: processing guida introduttiva alla programmazione visuale 11
  • 12. // ecco la variabile che gestisce // il raggio del cerchio int cerchio = 10; Il nome delle variabili è sempre meglio che sia “parlante”. Alcuni nomi però sono inibiti e non possono essere utilizzati per le variabili. Ad esempio non posso nominare una variabile “int” perchè facendo questo complicherei molto la vita a Processing che potrebbe fare confusione. Infatti “int” è anche un termine assegnato ad un comando. Di seguito una lista dei nomi di variabili che non possiamo usare in Processing: abstract assert boolean break byte case catch char class const continue default do double else enum extends false final finally float for goto if implements import init instanceof int interface long native new null package private protected public return setup short start static processing guida introduttiva alla programmazione visuale 12
  • 13. stop strictfp super switch synchronizedthis throw throws transient true try update void volatile while Questo aspetto è comune a praticamente tutti i linguaggi di programmazione. Un consiglio che posso dare ai programmatori italiani è proprio quello di dare un nome in italiano alle variabili. Poichè i comandi tipicamente sono in inglese si eviterà facilmente di utilizzare un nome vietato. Esiste poi una lista di variabili che gestisce autonomamente Processing. Quando ad esempio abbiamo generato la finestra: size(320, 240); Processing ha automaticamente immagazzinato in un due variabili “width” e “height” questi valori. Se in futuro vorremo utilizzare questi valori potremo utilizzarli richiamando direttamente le variabili. Variabili e calcoli matematici Le variabili normalmente vengono utilizzate anche per effettuare calcoli matematici. Le operazioni di base che si effettuano sono più “+”, meno ”-“, per ”*” e diviso “/”. Normalmente il risultato di un’operazione matematica viene memorizzato nelle variabili. Ad esempio: int x = 2 + 3; trasferisce il risultato della somma “2+3” nella variabile X al momento della sua inizializzazione “int”. Oppure: int x = 4; processing guida introduttiva alla programmazione visuale 13
  • 14. int y = 6; int s = x + y; int d = s / 2; int m = (x * y)-2; dichiara il valore delle variabili “x” e “y”, poi viene sommato e il risultato è memorizzato nella varibile “s” (da cui avremo s = 10). In “d” invece memorizziamo il risultato di della somma precedente dividendola per 2 (da cui otterremo d = 5). Infine nella quinta riga abbiamo una vera e propria espressione. Trasferiamo nella variabile “m” il risultato della moltiplicazione di “x” per “y” e successivamente, fuori dalle parentesi, sottraiamo 2 (da cui otteniamo m = 22). Da notare che il risultato di un calcolo matematico deve sempre essere associato a una variabile. Infatti se nella terza riga scriviamo solo: x + y; otterremo un errore quando manderemo in RUN il nostro sketch. L’uso delle parentesi cosi come nella matematica serve per dare la priorità ai calcoli. Inoltre moltiplicazione e sottrazione hanno la priorità su addizione e sottrazione. Le variabili posso essere utilizzate molte volte all’interno della stessa espressione. A volte siamo costretti a compiere diverse operazioni ma non ci interessato i risultati intermedi bensì solo il risultato finale. Nel seguente programma: int x = 4; int y = 6; int s = x + y; s = s / 2; dopo avere calcolato “x+y” e memorizzato il risultato in “s” utilizziamo nuovamente “s” nella riga successiva per memorizzare il valore “s” della riga precedente diviso per 2. Operando in questo modo abbiamo “risparmiato” una variabile però abbiamo perso il risultato temporaneo della somma “x + y”. Quando Processing processing guida introduttiva alla programmazione visuale 14
  • 15. eseguirà la quarta riga trasferirà in “s” il risultato della nuova operazione (“s/2”) e il precedente valore di “s” sarà perso. Iniziare a disegnare Le operazioni matematiche che si possono effettuare in Processing sono molte di più delle quattro operazioni di base, ma stiamo procedendo secondo un livello di difficoltà progressivo. Abbiamo capito come si scrive un’istruzione in Processing e abbiamo capito l’importanza della sintassi. Inoltre abbiamo introdotto il concetto di variabile nella programmazione. Questi primi elementi ci permettono di iniziare a scrivere un programma leggermente più complesso. Per fare questo però ci avvarremo dell’aspetto maggiormente potente in Processing, cioè le funnzionalità grafiche. Credo che comprendere una formula matematica sia molto più semplice se il risultato di questa formula viene tradotto in una dimensione grafica. Prima quindi di addentrarci nei meandri della programmazione e dell’uso intensivo della matematica iniziamo quindi ad osservare le funzionalità grafiche di Processing. La conoscenza delle funzionalità grafiche faciliterà molto lo sviluppo di formule matematiche più complesse. Abbiamo iniziato la nostra programmazione scrivendo tre righe: //Creiamo una finestra 320 x 240 pixel// size(320, 240); background(255); che, abbiamo visto cliccando su RUN, generano una finestra di sfondo bianco della dimensione di 320 pixel di larghezza e 240 pixel di altezza. Per disegnare qualche cosa dentro questa finestra è necessario prima di tutto comprendere il concetto di coordinate. L’asse delle X scorre in orizzontale mentre l’asse delle Y scorre in verticale. L’angolo in alto a sinistra della nostra finestra ha le coordinate (0, 0). L’angolo in basso a destra ha coordinate (320, 240). L’angolo in alto a destra ha coordinate (320, 0) mentre l’angolo in basso a sinistra ha coordinate (0, 240). figura 2 disegno delle coordinate processing guida introduttiva alla programmazione visuale 15
  • 16. L’istruzione grafica piùsemplice di Processing permette di generare un punto nello schermo. Questa è la sua sintassi: point(X, Y); questo comando grafico ha due parametri, “X” ed “Y” che indicano le coordnate della finestra nella quale verrà disegnato il punto. Se ad esempio decidessimo di disegnare il punto esattamente al centro della finestra che abbiamo appena creato sarà sufficiente aggiungere una quarta riga: //Creiamo una finestra 320 x 240 pixel// size(320, 240); background(255); point(160, 120); Dividendo per due la larghezza e l’altezza della finestra ottengo le coordinate “X,Y” del punto centrale della finestra. Per comprendere meglio il funzionamento del sistema delle coordinate è sufficiente cambiare i valori “X,Y” del comando point. Da notare che questi valori debbono necessariamente rimanere all’interno dell’intervallo della finestra stessa. Per generare più punti nella finestra aggiungo più volte la stessa istruzione cambiando le coordinate. Mantenendo fisso uno dei due valori delle coordinate si ottengono dei punti lungo l’asse verticale o orizzontale a seconda del valore tenuto fisso. size(320, 240); background(255); //Creiamo tre punti sull’asse verticale //tenendo il valore “X” stabile point(160, 60); point(160, 120); point(160, 180); L’aspetto centrale di Processing in quanto strumento didattico è proprio la facilità con la quale possiamo visualizzare dei principi matematici e statistici. Le coordinate X,Y le ritroviamo in infiniti sistemi e rappresentazioni. Manipolare in Processing i valori del processing guida introduttiva alla programmazione visuale 16
  • 17. comando “point” permette di comprendere immediatamente in modo visivo il funzionamento delle coordinate. Questa guida può essere letta anche come un’introduzione ai principi della matematica, della programmazione e degli algoritmi, possiamo vedere Processing come lo strumento più veloce per comprendere questi principi. Una volta compreso il principio delle coordinate sarà molto semplice con processing disegnare tutte le forme geometriche di base. Ad esempio questa è la sintassi del comando per disegnare una linea: line(x1, y1, x2, y2); Con questo comando viene eseguita una linea che come estremi due punti individuati con “X1,Y1” e “X2,Y2”. size(320, 240); background(255); //Creiamo una linea diagonale //che attraversa la finestra //dall’angolo in alto a sinistra //all’angolo in basso a destra line(0, 0, 320, 240); Per fare una linea in senso orizzontale il parametro Y dei due punti dovrà rimanere costante. Il seguente comando genera una linea che attraversa la finestra orizzontalmente alla sua metà. line(0, 120, 320, 120); Per disegnare diverse linee è sufficiente mettere un’istruzione dopo l’altra nello stesso Sketch. Per disegnare diverse linee con dei punti in comune è sufficiente scrivere più istruzioni dove ogni linea ha due coordinate uguali alla linea successiva. //figura composta da due linee //che hanno un punto in comune //100,120 line(0, 120, 100, 120); processing guida introduttiva alla programmazione visuale 17
  • 18. line(100, 120, 80, 220); Unendo delle linee possiamo disegnare triangoli, quadrilateri, rettangoli e linee spezzate. //triangolo prodotto //disegnando 3 linee line(0, 120, 100, 120); line(100, 120, 80, 220); line(80,220,0, 120); Ovviamente però Processing prevede le istruzioni per disegnare direttamente Triangoli, Quadrilateri, Rettangoli ed Ellissi. triangle quad rect ellipse Ecco spiegato di seguito il funzionamento di ogni istruzione: triangle (X1, Y1, X2, Y2, X3, Y3); Attraverso i tre punti vengono disegnati i tre lati del triangolo. quad (X1, Y1, X2, Y2, X3, Y3, X4, Y4); Attraverso i quattro punti vengono definiti i quattro lati del quadrilatero. Il quadrilatero che ne deriva può avere anche tutti i lati diversi e non avere lati paralleli. Importante però quando si disegna un quadrilatero è di seguire un ordine dei lati. Se ad esempio scrivete questa istruzione quad (1, 1, 50, 10, 100, 100, 130, 100); succede che anzichè generare un quadrilatero genererete due trinagoli. Ciò succede perchè nel passaggio dal secondo punto al terzo e dal terzo al quarto Processing segue l’ordine dei punti e quindi i lati del quadrilatero si incrocieranno. processing guida introduttiva alla programmazione visuale 18
  • 19. Scambiando il terzo punto con il quarto otterremo invece un quadrilatero: quad (1, 1, 50, 10, 130, 100, 100, 100); Per quanto riguarda il rettangolo Processing ragiona in modo leggermente diverso, ecco la sintassi: rect(x, y, width, height) si individua con i parametri “X,Y” l’angolo in alto a sinistra del rettangolo e successivamente si dichiara la larghezza e l’altezza del rettangolo. Ovviamente se “width” e “height” hanno lo stesso valore succede che il rettangolo diventa un quadrato. Infine ecco l’istruzione per generare ellissi e cerchi: ellipse (X, Y, width, height); Con “X, Y” si stabilisce il centro dell’ellisse mentre con “width, height” si stabiliscono larghezza e altezza dell’ellisse. Se i due parametri “width, height”sono uguali si ottiene un cerchio perfetto. Abbiamo quindi visto come si disegnano le figure geometriche di base con Processing. Gli esempi descritti sopra fanno sempre riferimento a delle forme “stabili” legate cioè a dei numeri “fissi”. Volendo effettuare dei disegni più complessi e dinamici potremmo associare le nostre forme a delle variabili. Inoltre le forme che abbiamo disegnato fanno sempre riferimento ad un contesto “neutrale”dove il colore di sfondo è sempre bianco e le figure sono bianche bordate di nero. Ad esempio il seguente Sketch size(320, 240); background(255); //Creiamo un quadrilatero quad (1, 1, 50, 10, 130, 100, 100, 100); //mettiamo sopra al quadrilatero un cerchio ellipse (20,20, 50, 50); processing guida introduttiva alla programmazione visuale 19
  • 20. produrrà graficamente il quadrilatero che conosciamo e successivamente sopra di esso un cerchio le cui coordinate del centro sono “20, 20” ed il cui raggio è 50. Il cerchio come possiamo vedere ha uno sfondo bianco pertano si sovrappone, coprendolo in parte, al quadrilatero. Questo comportamento ci spiega due aspetti di Processing. Prima di tutto dobbiamo capire che Processing come tutti i linguaggi di programmazione esegue i comandi leggendoli in sequenza. La sequenza di esecuzione diventa sempre più importante e strategica quando si complica lo Sketch. Inoltre le figure grafiche hanno un riempimento e non sono trasparenti. Per vedere meglio questo riempimento possiamo cambiare il colore della finestra. background(0); Canbiando il valore di background da 255 (bianco) a 0 (nero) vediamo ancora maglio che le forme geometriche create hanno un colore di riempimento. I numeri compresi tra 0 e 255 rappresentano tutte le gradazioni che vanno dal nero al bianco, cioè sono dei grigi sempre meno intensi che alla fine 255 diventa un bianco. Questa modalità di classificazione dei colori vale anche per il colore di riempimento delle forme. Quando questo colore non viene dichiarato Processing stabilisce autonomamente un colore (questo in informatica viene definito valore di default). Per vedere ad esempio quale è il colore di default delle finestre è sufficiente cancellare l’istruzione background dal nostro sketch. Mandando in run Processing vediamo che la finestra assume un colore di sfondo grigio. I comandi hanno valori di default diversi infatti le forme geometriche che abbiamo creato hanno un valore di default per il riempimento che è il bianco (255). Per cambiare il valore di default per il riempimento delle forme geometriche si utilizza l’istruzione: fill (); questa istruzione deve precedere il comando per la generazione della forma geometrica. Il seguente sketch processing guida introduttiva alla programmazione visuale 20
  • 21. size(320, 240); fill (80); //Creiamo un quadrilatero quad (1, 1, 50, 10, 130, 100, 100, 100); //mettiamo sopra al quadrilatero un cerchio ellipse (20,20, 50, 50); genera quindi una finestra con un colore di sfondo di default (grigio) e delle forme geometriche con un colore di sfondo stabilito dal valore tra parentesi del comando “fill”. 80 indica un grigio scuro. Il valore fill funziona per tutte le forme geometriche che verranno generate dopo di esso. Possiamo infatti vedere che sia il quadrilatero che il cerchio hanno lo stesso riempimento. Qualora volessimo generare forme geometriche con valori di sfondo diversi dobbiamo semplicemente mettere dei nuovi comandi fill size(320, 240); //Creiamo un quadrilatero fill (80); quad (1, 1, 50, 10, 130, 100, 100, 100); //mettiamo sopra al quadrilatero un cerchio fill (250); ellipse (20,20, 50, 50); Il fill valido è sempre l’ultimo e vale nello sketch finchè non ne dichiariamo uno nuovo. Il cerchio dello sketch qui sopra è pressochè bianco (250) il quadrilatero e grigio scuro (80) e se creassimo una nuoma forma geometrica dopo il cerchio senza specificare un nuovo fill esso sarebbe 250. Le forme grafiche hanno altri valori di default. Ad esempio disegnando le forme geometriche notiamo che il bordo della forma ha un colore e uno spessore. Il cerchio che abbiamo creato nel precedente Sketch ha il bordo nero, questo colore è di default e può essere cambiato mettendo, sempre prima dell’istruzione che genera la forma geometrica , l’istruzione: stroke (255); processing guida introduttiva alla programmazione visuale 21
  • 22. in questo caso il cerchio avrà un bordo bianco (255) e qualora sia bianco anche il riempimento ovviamente non avremo percezione del bordo stesso. Un modo più corretto per fare scomparire il bordo da una forma geometrica è l’apposito comando nostroke (0); così come possiamo fare scomparire il riempimento con noFill (0); Inoltre possiamo anche decidere lo spessore del bordo delle forme geometriche (e delle linee) attraverso l’istruzione strokeWeight(4); dove il valore tra parentesi indica lo spessore del bordo espresso in pixel. Da notare un aspetto importante: la “W” di Weight è maiuscola e come ho spiegato nelle prime pagine i comandi sono “case sensitive” pertanto dobbiamo scriverli tenendo presenti le maiuscole e le minuscole. In generale su questo aspetto però l’ambiente di sviluppo di Processing ci aiuta poichè se per errore digitiamo un comando errato (es: strokeweight) vediamo che Processing non modifica il colore del comando stesso lasciandolo nero. Quando invece digitiamo un comando che per Processing significa qualche cosa (es: strokeWeight) succede che immediatamente il testo viene cambiato di colore e diventa marrone. Da notare infine che in molti linguaggi di programmazione si segue questa convenzione, la prima parola di un comando si scrive in minuscolo la seconda parola (attacata) inizia sempre con una maiuscola, lo stesso vale per l’eventuali terza o quarta parola. Diversi altri parametri permettono di intervenire sulle forme geometriche ma per ora abbiamo visto quelli essenziali e possiamo procedere oltre nel nostro percorso di addestramento alla programmazione. In seguito scopriremo come gestire i colori (per ora abbiamo visto solamente come gestire i grigi, e come gestire ad esempio le trasparenze nonchè le curve e tante altre cose ...). processing guida introduttiva alla programmazione visuale 22
  • 23. Ora però è necessario un nuovo salto nella modalità di lavoro. Programmare veramente La programmazione che abbiamo visto fino ad ora è composta da una serie di comandi messi in sequenza. Processing elabora le istruzioni una dopo l’altra partendo dalla prima riga e terminando all’ultima. In pratica Processing legge i programmi che abbiamo fatto fino ad ora come noi leggiamo i contenuti di un libro. Abbiamo visto anche il concetto di variabile. Le variabili sono utili perchè invece di utilizzare sempre i numeri possiamo sostituirli con delle entità il cui stato varia con lo scorrere del programma. I disegni che abbiamo fatto fino ad ora sono molto semplici e sopratutto sono statici. Infatti tutte le istruzioni che abbiamo scritto vengono elaborate sequenzialmente ma ad una velocità tale percui quando premiamo il tasto RUN davanti a noi compare una figura apparentemente statica. Processing è un’applicazione che si presta bene per fare lavori di tipo statico (immagini fisse) ma si presta molto bene anche per fare animazioni. Inoltre anche nell’elaborazione di immagini statiche potrebbe succedere che vogliamo produrre molte volte una figura ad intervalli regolari oppure di dimensioni progressivamene crescenti. Questa tipologia di problematiche: animazioni e ripetizioni (iterazioni) possono essere risolte in modo veloce attraverso delle apposite istruzioni. Partiamo da un caso molto semplice: all’interno della nostra finestra vogliamo disegnare dei punti ad intervalli regolari sull’asse orizzontale, uno ogni 40 pixel. Disegniamo ora questi punti utilizzando il metodo più semplice che abbiamo visto. size(320, 240); background(255); //Creiamo sette punti //sull’asse orizzontale //tenendo il valore “Y” stabile point(40, 120); point(80, 120); point(120, 120); point(160, 120); processing guida introduttiva alla programmazione visuale 23
  • 24. point(200, 120); point(240, 120); point(280, 120); Abbiamo visto già nelle pagine precedenti tutte le istruzioni che permettono di generare questo nuovo Sketch. Premendo RUN vediamo sette punti a intervalli rogolari che attraversano lo schermo in senso orizzontale. Ora introduciamo l’uso delle variabili. Stabiliamo una variabile che chiamiamo “intervallo” e che ha il valore di 40, successivamente sostituiamo i valori delle coordinate X dei punti con le variabili. size(320, 240); background(255); // dichiaro la variabile int intervallo = 40; //Creiamo sette punti //sull’asse orizzontale //tenendo il valore “Y” stabile point(intervallo, 120); point(intervallo*2, 120); point(intervallo*3, 120); point(intervallo*4, 120); point(intervallo*5, 120); point(intervallo*6, 120); point(intervallo*7, 120); Abbiamo moltiplicato l’intervallo per dei valori progressivamente maggiori ottenendo esattamente lo stesso risultato del precedente Sketch. Il coefficiente di moltiplicazione che applichiamo all’invervallo stabilisce la distribuzione dei punti. Proviamo quindi a trasformare in variabile anche questo coefficiente, chiamandola coefficiente. size(320, 240); background(255); // dichiaro la variabile int intervallo = 40; // dichiaro la variabile // coefficiente int coefficiente = 1; processing guida introduttiva alla programmazione visuale 24
  • 25. //Creiamo sette punti //sull’asse orizzontale //tenendo il valore “Y” stabile point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; Leggendo con attenzione lo Sketch appena scritto vediamo che esso è diventato molto più lungo. Infatti per poter incrementare ogni volta il coefficiente è stata aggiunta l’apposita istruzione “coefficiente = coefficiente + 1;”. Comunque un primo vantaggio possiamo coglierlo dal fatto che osservando con attenzione lo sketch vediamo che le istruzioni sono sempre uguali. Infatti le due righe di istruzione: point(intervallo*coefficiente, 120); coefficiente = coefficiente + 1; si ripetono sette volte generando i sette punti. Per velocizzare l’operazione di scrittura dello sketch potremmo scriverlo facendo “copia” e “incolla” delle due righe fino a ripeterle sette volte. La logica della programmazione informatica sta esattamente in questi passaggi: - concepire tutti i passaggi che portano al risultato (abbiamo scritto nel primo Sketch tutte le istruzioni che portavano al risultato desiderato) - concepire questi passaggi in modo che siano ripetitivi (abbiamo scritto nel terzo Sketch istruzioni ripetitive che portano al risultato desiderato) processing guida introduttiva alla programmazione visuale 25
  • 26. - trasformare i passaggi da ripetitivi a ricorsivi (ora trasformeremo le operazioni ripetitive in ricorsive scrivendo un “ciclo”): size(320, 240); background(255); // dichiaro la variabile int intervallo = 40; // dichiaro la variabile // coefficiente int coefficiente = 1; //Creiamo sette punti //sull’asse orizzontale //tenendo il valore “Y” stabile for (coefficiente = 1; coefficiente < 8; coefficiente = coefficiente+1) { point(intervallo*coefficiente, 120); } L’unico elemento nuovo nello Sketch precedente è esattamente l’istruzione “for” che ha la seguente sintassi: for (coefficiente = 1; coefficiente < 8; coefficiente = coefficiente+1) { point(intervallo*coefficiente, 120); } I principi di ricorsività vengono stabiliti tra parentesi dopo avere scritto l’istruzione “for”. Tra parentesi troviamo tre elementi separati da “;”. Il primo elemento “coefficiente = 1” stabilisce il valore di partenza del ciclo. Il secondo elemento “coefficiente < 8” stabilisce il valore di interruzione del ciclo. Il terzo elemento stabilisce l’aggiornamento del valore che avverrà ricorsivamente (l’incremento della variabile) che nel nostro caso è “coefficiente = coefficiente+1”. In seguito all’istruzione “for” tra le parentesi graffe vengono messe le operazioni da compiere durante tutta la durata del ciclo “point (intervallo*coefficiente, 120)”. processing guida introduttiva alla programmazione visuale 26
  • 27. Leggiamo come se fosse scritta in lingua italiana l’istruzione “for”del nostro ciclo: Incrementa il coefficiente di una unità e finchè il suo valore è minore di 7 disegna un punto. Attraverso le istruzioni di tipo “for” possiamo quindi ripetere un’operazione finchè non si verifichi una condizione di interruzione. Abbiamo quindi sintetizzato il nostro sketch, da notare che ora, qualora volessimo disegnare 100 punti invece di 7 la lunghezza dello sketch sarebbe sempre la stessa mentre invece nella modalità precendente avremmo dovuto scrivere 100 righe di codice, una per punto. Il seguente Sketch disegna 100 punti, con un intervallo tra un punto e l’altro di 3 pixel: size(320, 240); background(255); // dichiaro la variabile int intervallo = 3; // dichiaro la variabile // coefficiente int coefficiente = 1; //Creiamo sette punti //sull’asse orizzontale //tenendo il valore “Y” stabile for (coefficiente = 1; coefficiente < 101; coefficiente = coefficiente+1) { point(intervallo*coefficiente, 120); } Per fare questa semplice modifica abbiamo solamente modificato la variabile “int intervallo = 3;” ed abbiamo cambiato il valore di interruzione del ciclo “for” con “coefficiente < 100”. La verifica di interruzione del ciclo ”for” avviene attraverso un simbolo comunemente conosciuto: “<”. In processing è possibile anche controllare se un valore è maggiore “>” oppure se un valore è uguale “==”. Nel caso di uguale (come in molti linguaggi di programmazione) si utilizza due volte il simbolo “=” per evitare che il programma compia un’operazione sulla variabile. Pertanto quando scriviamo: processing guida introduttiva alla programmazione visuale 27
  • 28. X = 5 trasferiamo il valore “5” nella variabile “X” Mentre se scriviamo X == 5 controlliamo se il valore di X è uguale (==) a 5. La programmazione in Processing ci permette quindi di evitare di scrivere infinite operazioni descrivendole una ad una. Attraverso i cicli “for” possiamo ripetere delle operazioni infinite volte cambiando ogni volta l’operazione grazie all’uso delle variabili. Le condizioni Un’altra istruzione (oltre al ciclo “for”) è determinante nel processo di apprendimento della programmazione. Questa istruzione è “if”. Continuiamo a lavorare nel nostro precedente Sketch e modifichiamolo decidendo che i nostri punti devono diventare delle linee quando il valore del “coefficiente” supera la soglia di 90 (elimino i commenti per risparmiare “carta” visto che sono presenti nello Sketch precedenti). size(320, 240); background(255); int intervallo = 3; int coefficiente = 1; for (coefficiente = 1; coefficiente < 101; coefficiente = coefficiente+1) { if (coefficiente > 90) { line (intervallo*coefficiente, 120, intervallo*coefficiente, 130); } point(intervallo*coefficiente, 120); } Abbiamo aggiunto l’istruzione “if”: if (coefficiente > 90) { line (intervallo*coefficiente, 120, intervallo*coefficiente, 130); } processing guida introduttiva alla programmazione visuale 28
  • 29. che controlla se il coefficiente è maggiore di 90 e qualora lo sia disegna una linea verticale lunga 10 pixel (notare il valore della coordinata Y che è prima 120 poi 130). Mandando in RUN lo sketch completo vediamo che Processing disegna 90 punti e poi inizia a disegnare delle linee. La gestione delle condizioni nella programmazione è determinante, infatti ogni volta che verifichiamo se una condizione si verifica automaticamente creiamo un bivio nel percorso possibile che può compiere il programma. Quando al mattino usciamo di casa controlliamo se piove e qualora stia piovendo prendiamo l’ombrello. In quel momento compiamo un’operazione di tipo “if”. Quando all’interno di un programma ad esempio vogliamo gestire le possibili interazioni con l’utente che lo userà dobbiamo farlo attraverso delle operazioni “if”. Tutti i software che producono delle interazioni con l’utente lo fanno ragiornando attraverso dei comandi di tipo “if”. I cicli “for” insieme ai controlli “if” sono due elementi centrali della logica di programmazione (in processing e praticamente in qualunque altro linguaggio di programmazione). Il controllo “if” permette anche di gestire la condizione negativa (detta “else” ossia altrimenti). Pertanto possiamo decidere anche di cambiare il nosro sketch così come segue: size(320, 240); background(255); int intervallo = 3; int coefficiente = 1; for (coefficiente = 1; coefficiente < 101; coefficiente = coefficiente+1) { if (coefficiente > 90) { line (intervallo*coefficiente, 120, intervallo*coefficiente, 130); } else { point(intervallo*coefficiente, 120); } } Oltre al controllo precedente (“if coefficiente > 90”) abbiamo aggiunto la verifica della condizione negativa “else”. In questi passaggi è importante seguire anche l’uso delle parentesi poichè se processing guida introduttiva alla programmazione visuale 29
  • 30. utilizzate in modo errato producono degli errori in fase di esecuzione. Rispetto all’uso delle parentesi vale sempre una regola semplice: le parentesi aperte debbono essere tante quante le parentesi chiuse. Inoltre le parentesi sono sempre legate, quindi se si apre una parentesi tonda si deve chiudere la parentesi tonda. Quando si apre una graffa si deve chiudere la graffa. Inoltre le parentesi possono essere nidificate, messe cioè una dentro l’altra. Nello Sketch sopra ad esempio abbiamo messo dentro alle parentesi del ciclo “for” (che quindi inglobano il resto delle istruzioni) le parentesi relative ad “if” e ad “else”. Possiamo dire che abbiamo messo due piccole scatole (“if” e “else”) dentro una scatola più grande (“for”). Programmare le animazioni Le istruzioni che abbiamo visto fino ad ora ci hanno permesso di capire i principi base della programmazione. Per generare delle forme grafiche è sufficiente scrivere le specifiche istruzioni. Le forme grafiche hanno sempre delle coordinate e dei valori (colore, spessore...) che possono essere espressi in numeri o attraverso delle variabili. L’esecuzione delle istruzioni da parte di Processing procede linearmente a meno che, attraverso le istruzioni for non realizziamo dei cicli. Nel caso in cui volessimo però realizzare delle animazioni dobbiamo ragionare in modo diverso. Un’animazione è composta da fotogrammi (immagini fisse) successivi. L’esecuzione dei fotogrammi ad una velocità sufficiente genera un effetto di animazione nel nostro cervello. Processing è un software che ci permette di disegnare attrvaerso le istruzioni grafiche e ci permette anche di disegnare in movimento. Riconfiguriamo ora lo Sketch realizzato precedentemente dandoci un nuovo obiettivo. Produrre attraverso un’animazione dei punti successivi che compaiono progressivamente. Per ottenere questo nuovo effetto dobbiamo utilizzare le istruzioni che permettono di gestire le funzioni: // configuro i parametri // di esecuzione void setup () { processing guida introduttiva alla programmazione visuale 30
  • 31. size (320,240); background (255); } int intervallo = 0; // definisco la funzione // dentro la funzione // metto le istruzioni ricorsive void draw (){ frameRate (1); point(intervallo, 120); intervallo = intervallo + 10; } Le funzioni utilizzate in questo nuovo Sketch sono due: void setup () {} void draw () {} Con “void setup” vengono definite tutte quelle parti del programma che rimarranno effettive durante la sua esecuzione. Le istruzioni interne alla funzione “void setup” vengono eseguite una sola volta. Infatti dentro le parentesi “{}” sono state messe le due istruzioni tipiche di ogni Sketch per la definizione della finestra e del suo colore di sfondo. Inoltre è stata anche messa l’inizializzazione della variabile “intervallo” che è necessaria un’unica volta. Con “void draw”viene invece definita la funzione ricorsiva che verrà eseguita ricorsivamente senza sosta. “frameRate (1);” stabilisce la velocità dell’animazione che ho impostato ad 1 fotogramma al secondo in modo al fine di cogliere bene gli effetti dello Sketch. Poi metto l’istruzione per disegnare il punto e l’istruzione per spostare di intervalli regolari il punto stesso (intervallo = intervallo + 10). Quando verrà mandato in RUN lo Sketch si otterrà un’animazione alla velocità di un frame al secondo dove compare un nuovo punto ogni frame. Questo punto (grazie al contatore) avrà ad ogni frame una coordinata Y incrementata di 10. Mandando in RUN lo Sketch così come è stato configurato succede che i punti creati nel fotogramma precedente rimangono persistenti nel video pertanto ad ogni fotogramma avremo un punto in più. Qualora invece volessimo avere un effetto di spostamento del punto dovremmo ad ogni nuovo frame cancellare il punto creato nel fotogramma precedente. Per fare questo è sufficiente spostare processing guida introduttiva alla programmazione visuale 31
  • 32. l’istruzione “background (255);”dalla funzione “setup” alla funzione “draw”. Mandando nuovamente in RUN lo Sketch modificato notiamo che il punto del frame precedente scompare ed abbiamo un effetto di movimento (anche se molto a scatti e lento). Per velocizzare il movimento è sufficiente modificare i parametri frameRate (lo impostiamo a 5 poi a 15). Per dare maggiore fluidità è sufficiente abbassare l’incremento costante della variabile “intervallo”; anzichè 10 mettiamo 3 poi 1. Continuando a modificare questi due parametri possiamo capire sempre meglio il loro uso. Da ricordare che nel cinema e nella televisione si lavora all’incirca ad una frequenza di 25 fotogrammi al secondo. Processing ha un valore di default del “frameRate” di 60. Pertanto se all’interno della funzione “draw” non dichiariamo una velocità questo valore sarà automaticamente impostato a 60 (molto veloce). Da notare infine che, mandando in esecuzione lo Sketch, il punto si sposta progressivamente da sinistra a destra finchè non scompare. In realtà, pur scomparendo il punto Processing continua ad elaborare lo Sketch incrementando il valore “intervallo” anche oltre la dimensione della finestra dichiarata in “size”. Questo aspetto dovrà essere tenuto presente quando verranno programmati degli Sketch sempre più complessi poichè in termini di elaborazione essi impegnano il computer pur non generando alcun effetto visibile. Farsi in casa una funzione I processi base della programmazione sono stati introdotti. Le funzioni sono molto importanti poichè permettono di eseguire in modo ricorsivo delle operazioni. La programmazione in Processing permette anche di definire delle funzioni da richiamare quando se ne ha bisogno. Ad esempio possiamo definire una funzione che disegna due punti che si muovono da sinistra a destra. Costruisco una funzione come segue: void punti () { // con il controllo if // faccio in modo di ripartire // ogni volta che esco dallo schermo if (intervallo > 320) { intervallo = 10; processing guida introduttiva alla programmazione visuale 32
  • 33. } intervallo = intervallo + 10; point (intervallo, 120); point (intervallo +1, 118); } dopo l’istruzione che introduce le funzioni (void) viede dato un nome alla funzione stessa. In questo caso “punti”. Poi per vedere l’effetto in modo continuativo utilizzo anche una istruzione if che praticamente controlla se i punti hanno superato la dimensione dello schermo “if (intervallo > 320)”. In caso affermativo riporto la variabile “intervallo” al suo valore di partenza (intervallo = 10;) e quindi i punti riappariranno nello schemo a sinistra in modo infinito. Le due istruzioni “point” definiscono la posizione dei due punti che scorreranno in senso orizzontale (infatti come coordinata X hanno una variabile mentre come coordinata Y hanno un numero fisso). L’utilità delle funzioni definite sta nel fatto che possono essere richiamate quando sono necessarie. Pertanto una volta definite potranno essere utilizzate molte volte. Di seguito uno sketch che richiama la funzione “punti” (tolgo i commenti ricorsivi dallo Sketch per brevità). int intervallo = 10; void setup () { size (320,240); } void draw (){ frameRate (15); background (255); punti (); } void punti () { if (intervallo > 320) { intervallo = 10; } intervallo = intervallo + 10; point (intervallo, 120); point (intervallo +1, 118); processing guida introduttiva alla programmazione visuale 33
  • 34. } Leggendo il contenuto della funzione “void draw ()” vediamo il richiamo alla funzione creata “punti ();”. Per richiamare una funzione creata è sufficiente quindi scrivere il nome della funzione e mettere le due parentesi tonde e la virgola. Il flusso di esecuzione dello Sketch salterà quindi alla funzione “punti” e la scorrerà come se fosse un sottoprogramma. Terminata la funzione Processing tornerà a leggere l’istruzione subito dopo il richiamo. Da ricordare che tutte le istruzioni della funzione “void draw ()” sono eseguite da processing in modo infinito. E’ comunque possibile interrompere questo ciclo infinito attraverso l’istruzione “noLoop ();” sia in un punto specifico durante l’esecuzione della funzione “draw” sia come caratteristica generale dello sketch mettendo l’istruzione nell’area “setup”. Volendo far ripartire il loop infinito di “draw” è invece sufficiente mettere l’istruzione “loop ();” nel punto desiderato. Variabili, funzioni, interazioni (if) e cicli rapresentano la base della programmazione. Chi ha letto e compreso tutto ciò che è scritto nelle pagine precedenti può tranquillamente dire in giro che conosce i rudimenti della programmazione. processing guida introduttiva alla programmazione visuale 34
  • 35. Seconda Parte I colori Molte istruzioni sono state volontariamente tralasciate nella prima parte del testo perchè l’intento era far comprendere i principi base e successivamente incrementare la conoscenza intorno ad essi. Ad esempio nella Prima parte ho descritto il metodo utilizzato in Processing per definire il bianco, il nero e tutte le tonalità di grigio che stanno in mezzo. Traducendo in termini informatici e matematici la modalità di classificazione utilizzata da Processing per le scale di grigio possiamo dire che vengono utilizzati 8 bit. Infatti 8 bit permettono di ottenere 28 (256) combinazioni diverse (da 0 a 255). Il criterio che processing utilizza per i colori è praticamente lo stesso solamente che applica la scala ai tre colori primari utilizzati per classificare i colori negli schermi (anche quelli televisivi). Questi colori sono Il Rosso il Verde (Green) e il Blu, il metodo viene infatti chiamato RGB. Processing utilizza 8 bit per classificare ognuno dei tre colori primari del metodo RGB. Vediamo prima di tutto un semplice Sketch per capire meglio il metodo: size (320, 240); fill(255, 255, 255); ellipse (50, 50, 20, 20); Lo Sketch produce un cerchio (ellipse) di colore bianco poichè nella istruzione “fill” sono stati impostati i parametri RGB al massimo valore (255, 255, 255). Ne consegue che se impostiamo tutti e tre i parametri al mimimo otteniamo il nero (0, 0, 0). Questo metodo è anche detto additivo. I tre numeri hanno una posizione fissa, il primo indica il Rosso, il secondo il Verde e il tezo il Blu. Di seguito una breve tabella con alcuni esempi di colore ottenuti attraverso il metodo RGB: (255, 0, 0) = Rosso (0, 255, 0) = Verde (0, 0, 255) = Blu processing guida introduttiva alla programmazione visuale 35
  • 36. (255, 255, 0) = Giallo (150, 150, 150) = Grigio (250, 200, 200) = Rosa Le combinazioni possibili prodotte da 24 bit sono circa 16 milioni di colori. Il metodo RGB può essere applicato in sostituzione del metodo a 8 bit. Ad esempio per tornare allo Sketch precedente potremmo stabilire di voler disegnare un cerchio bianco con bordo rosso. Per fare questo utilizziamo un’istruzione che abbiamo già visto “stroke” però in questo caso dichiariamo i 3 colori primari. size (320, 240); fill(255, 255, 255); stroke (255, 0, 0); ellipse (50, 50, 20, 20); Inoltre aggiungendo l’istruzione background possiamo anche stabilire il colore di sfondo della finestra. Ad esempio se allo sketch precedente aggiungiamo l’istruzione “background (0, 0, 0)” dopo l’istruzione “size”, otteniamo uno sfondo verde. Trasparenza Processing permette anche di gestire un quarto parametro per gestire i colori. Anche questo quarto parametro viene gestito con uno spettro di 8 bit, esso è la trasparenza (anche detto canale alpha). Vediamo uno Sketch: size (320, 240); fill(0, 0, 255, 200); ellipse (50, 50, 20, 20); fill(255, 0, 0, 100); ellipse (40, 40, 20, 20); fill(255, 0, 255, 50); ellipse (20, 20, 50, 50); Il precedente Sketch produce tre cerchi con colori diversi e gradi di riempimento diversi (il quarto parametro dell’istruzione “fill”). processing guida introduttiva alla programmazione visuale 36
  • 37. Quando il canale Apha è impostato a 0 la figura risulta completamente trasparente mentre quando il canale è impostato a 255 la figura risulta essere piena. Il grado di trasparenza è particolarmente utile quando si hanno delle figure sovrapposte e si vuole lasciare trasparire le figure sottostanti. Eseguendo il precedente Sketch possiamo notare che i tre cerchi sono sovrapposti secondo l’ordine definito nella scrittura dello Sketch: il primo cerchio risulta essere più in fondo e vicino allo sfondo, mentre l’ultimo cerchio risulta essere più in superficie e quindi sopra i due cerchi scritti precedentemente. Il grado di trasparenza è applicabile anche ai grigi. Ecco una tabella esplicativa delle possibili situazioni, riportata all’istruzione “fill” ma estensibile a “background”: fill (100); = riempimento grigio fill (100, 50); = riempimento grigio con un alto livello di trasparenza fill (255, 0, 0); = riempimento con metodo RGB fill (255, 0, 0, 120); = riempimento con metodo RGB e un medio livello di trasparenza Un’ultima cosa interessante sui colori riguarda le variabili. E’ possibile definire delle variabili di tipo colore e successivamente richiamare il colore direttamente scrivendo il nome della variabile. color rosso = color(255, 0, 0); fill(rosso); Ad esempio nelle due righe sopra ho definito il colore rosso e successivamente lo richiamo all’interno di un parametro fill. Questà opportunità permette di gestire colori particolari dei quali magari si è già provata in passato la combinazione. In questo modo mettendo all’inizio dello Sketch il codice del colore sarà più facile in seguito nello Sketch richiamarlo. Nei semplici Sketch questo tipo di funzionalità potrebbero sembrare inutili, ma quando si inizia a scrivere degli Sketch lunghi centinaia di righe ci si accorge dell’utilità di queste funzioni (nonchè dei commenti “//”). Il caso Quando si realizza arte con il computer i colori sono ovviamente determinanti. Designare senza colori è molto più difficile e limitativo. Mentre alcuni tipi di disegni possono essere facilmente processing guida introduttiva alla programmazione visuale 37
  • 38. riprodotti anche in scale di grigio, altri tipi di rappresentazione necessitano dei colori. Se ben usata, l’opzione dei colori permette di ottenere dei risultati e delle rappresentazioni visive molto più efficaci. C’è un altro aspetto concettuale che riguarda la programmazione che è altrettanto determinante: la casualità (random). Generare dei numeri a caso attraverso il computer permette di ottenere delle forme visuali molto più credibili che non utilizzando delle rigide formule trigonometriche. Le numerazioni casuali sono molto utili ad esempio quando si vuole simulare un movimento di un “soggetto” organico oppure quando si vuole disporre in modo naturale degli oggetti. Ad esempio vuolendo simulare una distesa d’erba potremmo in teoria decidere di mettere un filo ogni 4 pixel ma questa disposizione così “rigida” e costante darebbe immediatamente un effetto estetico di artificialità all’immagine risultante. Se invece disponiamo i fili d’erba in modo casuale entro un certo intervallo (tra 1 e 6 pixel) otteniamo un effetto naturale nella distribuzione dell’erba stessa. Inoltre la casualità è molto importante anche quando si vogliono gestire dei giochi. Tutti gli eventi a partire da un lancio di moneta o di dado possono essere gestiti attraverso la generazione di un evento casuale nel computer. La casualità ha quindi uno spazio importante nella generazione di immagini e nella gestione delle animazioni fatte con Processing e con qualunque altro software. Da notare inoltre che la casualità in quanto tale non è gestibile dai computer. Infatti i computer ragionano in base a regole molto rigide e cicliche e quando gli si chiede di generare un numero casuale essi hanno difficoltà e quindi vanno alla ricerca di eventi da misurare. Il movimento del mouse è un tipico evento misurato dal computer che poi rielaborato più volte produce un numero casuale. Questo aspetto così complesso per il computer è completamente invisibile agli utenti ma è emblematico di quanto sia ritenuto importante il fattore casuale nella programmazione. Nonostante il computer non sia “geneticamente” in grado di produrre eventi casuali, gli si chiede di gestirli perchè attraverso questa casualità si possono simulare infiniti eventi. Modifichiamo quindi l’ultimo Sketch della prima parte utilizzando un fattore casuale: int intervallo = 10; void setup () { processing guida introduttiva alla programmazione visuale 38
  • 39. size (320,240); } void draw (){ frameRate (5); background (255); punti (); } void punti () { if (intervallo > 320) { intervallo = 10; } intervallo = intervallo + int (random (20)); point (intervallo, 120); point (intervallo +1, 118); } Nella funzione “void punti” ho corretto la linea che calcola il salto che i punti devono compiere ad ogni nuovo frame: intervallo = intervallo + int (random (20)); Precedentemente il valore di incremento era “10” mentre ora il valore di incremento (che definisce lo spostamento dei punti) sarà un valore casuale compreso tra zero e 20 (int (random (20)); ). “random (20); genera un numero casuale con virgola (di tipo “float”) compreso tra 0 e 20. L’istruzione “int ()” serve ad arrotondare i numeri con decimali in numeri interi. Questa istruzione “int” è necessaria in quanto Processing non permette di mescolare numeri con virgola (di tipo float) con numeri interi (di tipo int). Mandando in RUN lo Sketch vediamo che ora i punti si spostano sempre da sinistra a destra ma procedendo in modo irregolare a volte hanno delle accelerazioni mentre altre volte procedono lentamente. Questo andamento è casuale e lanciando più volte lo Sketch si otterranno sempre risultati diversi. Osservando i punti compiere questo tipo di movimenti abbiamo un effetto di movimento che suscita molta più curiosità, la sensazione che dona questo tipo di movimento è più organica e “viva” che non il movimento rettilineo uniforme del precedente Sketch. Per modificare l’effetto degli scatti possiamo agire su diversi parametri. Aumentando il valore di random (20) otteniamo scatti sempre più processing guida introduttiva alla programmazione visuale 39
  • 40. variegati, mentre otteniamo scatti meno evidenti mettendo dei valori più bassi. Inoltre, aumentando il “framerate” otteniamo maggiore velocità dell’animazione con più fluidità nel movimento dei punti. Interveniamo nuovamente sullo Sketch al fine di aumentare l’effetto organico del movimento: int intervallo = 10; void setup () { size (320,240); } void draw (){ frameRate (10); background (255); punti (); } void punti () { if (intervallo > 320) { intervallo = 10; } intervallo = intervallo + int (random (5)); point (intervallo, int (random (118, 121))); point (intervallo +1, int (random (116, 119))); } Ora, analizzando la funzione “void punti” vediamo che ho inserito un fattore di casualità anche nello spostamento sulla coordinata Y. Pertanto i punti si sposteranno anche leggermente in alto o in basso durante il loro consueto movimento verso destra. Analizzando l’istruzione vediamo che tra parentesi questa volta ci sono due parametri “int (random (116, 119))”. Quando l’istruzione random contiene due parametri significa che è stato definito un parametro inferiore e un parametro superiore dell’intervallo casuale. Nello Sketch precedente, il valore di Y 120 per il primo punto, ora invece sarà un valore casuale compreso tra 118 e 121. processing guida introduttiva alla programmazione visuale 40
  • 41. Mandando in RUN questo ultimo Sketch vediamo che i due punti spostandosi leggermente anche in alto e in basso avranno un effetto ancor più organico. Sembreranno volare come due mosche. Più avanti affronteremo ancor più approfonditamente questo concetto. Per il momento l’utilizzo della funzione “random” sarà molto utile perchè ci permetterà di osservare degli esempi più complessi e variegati, a volte dai comportamenti inattesi (perchè casuali). Curve Abbiamo già esplorato le forme grafiche di base di Processing (point, line, rect, triangle, quad, ellipse). Osservando i cicli e le funzioni abbiamo capito che possiamo assegnare le coordinate di queste forme geometriche a delle variabili anche casuali. Processing permette anche di generare delle curve secondo un metodo detto di Bezier. In pratica possono essere dichiarate, oltre ai due punti di inizio e fine della curva, anche le tangenti ai due punti. Vediamo un esempio scrivendo il seguente Sketch e mandandolo in RUN: size (320, 240); noFill (); bezier(10, 20, 100, 5, 280, 155, 10, 175); Il punto di inizio e di fine della curva sono la prima e la quarta coordinata dell’istruzione. La seconda e la terza coordinata indicano invece le tangenti. Per capire meglio cosa siano le tangenti consiglio di aggiungere due istruzioni in grado di visualizzarle: size (320, 240); noFill (); bezier(10, 20, 100, 5, 280, 155, 10, 175); line (10,20, 100,5); line (10,175, 280,155); Grazie alle due linee appena disegnate possiamo ora vedere le tangenti. Da notare che la curva risultante dalle nostra istruzioni tende ad essere più accentuata verso il basso. processing guida introduttiva alla programmazione visuale 41
  • 42. Osservando la tangente più in basso comprendiamo il motivo. La tangente è molto più “lunga” pertanto essa “attrae” molto di più la curva. Semplificando possiamo vedere la curva di Bezier come se fosse un elastico: con la prima e la quarta coordinata vengono fissati (inchiodati) i punti di inizio e fine dell’elastico. Attraverso la seconda e terza coordinata si “attrae” l’elastico. Quanto più lontane sono le coordinate di attrazione tanto più l’elastico sarà teso e quindi la curva sarà più accentuata. Per avere prova della desrcizione appena effettuata scrivete la seguente istruzione: bezier(10, 20, 10, 20, 10, 175, 10, 175); Il punti di tiraggio dell’elastico sono ora gli stessi dei punti di terminazione dell’elastico stesso. Ne risulta che la curva di Bezier è una linea retta (perchè il “tirante” non è attivo avendo le stesse coordinate del punto). Attraverso questo metodo possiamo disegnare praticamente qualunque tipo di curva. Questa funzionalità risulterà particolarmente utile quando vorremo generare delle forme organiche che molto difficilmente hanno spigoli e angoli netti. Lo Sketch di seguito ci mostra il variare di una curva di bezier al variare delle coordinate delle tangenti: int contatore = 10; void setup () { size (320,240); } void draw (){ frameRate (10); background (255); //incremento il contatore contatore = contatore + 1; // definisco la curva di bezier // associando le tangenti // a un contatore per osservare // il cambiamento della curva bezier (10,10, contatore, 10, contatore, 200, 60,200); } processing guida introduttiva alla programmazione visuale 42
  • 43. Osservando infine il risultato delle nostre curve notiamo che esse hanno sempre un effetto di scalettatura. Questo effetto (detto aliasing) può essere eliminato attraverso l’istruzione “smooth ();” da mettere all’inizio dello Sketch. L’effetto sarà di una curva molto più “morbida”. In termini elaborativi questa gradevole funzionalità estetica di ammorbidimento aumenterà l’impegno del computer. Ovviamente il fenomeno avverrà quando avremo disegnato molte curve e avremo delle animazioni molto veloci. Complichiamo ulteriormente il nostro lavoro introducendo anche un fattore di casualità nella generazione della curva. Questo esercizio è utile perchè viene formulato in modo nuovo uno Sketch contenente solo funzionalità già viste. Lo Sketch mandato in RUN genera una curva di bezier che nel tempo si espande verso destra o verso sinistra seguendo la casualità: int contatore = 10; // la variabile casuale float ai = 1; void setup () { size (320,240); smooth (); } void draw (){ frameRate (10); background (255); // genero un numero casuale ai = random (1); // controllo il numero “estratto” if (ai > 0.5) { contatore = contatore + 2; bezier (100,10, contatore, 10, contatore, 200, 120,200); } else { contatore = contatore - 2; bezier (100,10, contatore, 10, contatore, 200, 120,200); } } processing guida introduttiva alla programmazione visuale 43
  • 44. La variabile “ai” è legata alla generazione di un numero casuale (con decimali e quindi di tipo float) compreso tra 0 e 1. La probalità che questo numero sia superiore o inferiore a 0.5 è del 50%. Tendenzialmente quindi avremo una curva che si muove casualmente verso destra e verso sinistra che però probabilisticamente tende ad essere stabile (cioè tende a ritornare alla sua posizione di partenza. Modificando l’istruzione “if (ai > 0.5)” ad esempio in “if (ai > 0.4)” altereremo probabilisticamente rapporto e quindi la curva tenderà a modificarsi verso una direzione. I vettori Quando nella programmazione si parla di vettori non ci si riferisce a delle forme grafiche bensì a dei contenitori. Abbiamo già visto nella prima parte il tipo di contenitori più diffusi nella programmazione: le variabili. I vettori sono delle variabili concatenate in sequenza. Il termine inglese per definire i vettori è Array e questi sono alcuni esempi di istruzioni: int[] vettore; float [] vettore2; Nel primo caso abbiamo la dichiarazione di un vettore che conterrà dei valori interi mentre nel secondo caso abbiamo la dichiarazione di un vettore che conterrà dei valori con virgola. Una volta dichiarato il tipo di vettore è necessario inizializzarlo: vettore = new int[50]; vettore2 = new float[150]; Nel primo caso abbiamo inizializzato un vettore che conterrà un massimo di 50 valori diversi mentre nel secondo caso abbiamo inizializzato un vettore che ne conterrà 150. Queste dimensioni sono normali in molti tipi di programmi e questo è proprio il motivo per il quale si usano i vettori anziche le variabili. Nel caso in cui si vogliano immagazzinare 50 informazioni usando le variabili sarebbe necessario inizializzare 50 diverse variabili. I vettori sono quindi il modo più elegante e rapido per organizzare i dati all’interno di un programma. Troviamo i vettori praticamente in tutti i linguaggi di programmazione. processing guida introduttiva alla programmazione visuale 44
  • 45. Vediamo ora uno Sketch che utilizza i vettori: size (320, 240); smooth (); noFill (); int[] curva = new int[10]; // ciclo per riempire l'array for (int cicli = 0; cicli < 10; cicli = cicli +1) { curva[cicli] = int (random (200)); } // ciclo di lettura dell'array for (int cicli = 0; cicli < curva.length; cicli = cicli +1) { bezier(curva[cicli], 0, curva[cicli], 100, 200, 240, 240, 240); } // secondo ciclo di lettura dell'array for (int cicli = 0; cicli < curva.length; cicli = cicli +1) { ellipse (curva[cicli], 5, 10, 10); } Nella quarta riga osserviamo l’struzione di inizializzazione dell’array: “int[ ] curva = new int[10];” che sarà quindi composto da numeri interi e si chiamerà “curva”. Subito dopo leggiamo un ciclo “for” che ha la funzione di riempire l’array. Il ciclo compie 10 “giri” e mette in ogni casella dell’array un valore casuale compreso tra 0 e 200 (“curva[cicli] = int (random (200))”). Successsivamente abbiamo due altri cicli. Con il primo ciclo vengono disegnate 10 curve i cui parametri sono letti dall’array precedentemente creato ( “bezier(curva[cicli], 0, curva[cicli], 100, 200, 240, 240, 240)”). Da notare che il parametro di chiusura del ciclo “for” viene stabilito attraverso un controllo della lunghezza dell’array (“cicli < curva.length”). Curva.lenght dichiara infatti la lunghezza dell’array che avevamo chiamato “curva”. Il secondo ciclo di lettura dell’array è simile al primo con la differenza che vengono disegnati dei cerchi in corrispondenza del termine superiore delle curve create precedentemente. Questo secondo ciclo è stato creato appositamente per dimostrare l’utilità di un array. Infatti nel secondo ciclo è stato riletto tutto il processing guida introduttiva alla programmazione visuale 45
  • 46. contenuto memorizzato nell’array e che volendo potrebbe essere ulteriormente letto per funzioni future. L’array quindi ci permette di immagazzinare grandi quantità di dati evitando di dover creare numerose variabili. Inoltre grazie alla loro sequenzialità gli array facilitano l’accesso per la lettura e la scrittura attraverso i cicli. Il seguente Sketch compie le stesse funzioni del precedente in modalità “continuous” generando un effetto di animazione. In questo caso il vettore viene riempito e svuotato automaticamente ad ogni nuovo ciclo automatico di “void draw”. int[] curva = new int[10]; void setup () { size (320, 240); smooth (); noFill (); frameRate (10); } void draw () { // azzero lo schermo background (255); // ciclo per riempire l'array for (int cicli = 0; cicli < 10; cicli = cicli +1) { curva[cicli] = int (random (200)); } // ciclo di lettura dell'array for (int cicli = 0; cicli < curva.length; cicli = cicli +1) { bezier(curva[cicli], 0, curva[cicli], 100, 200, 240, 240, 240); } // secondo ciclo di lettura dell'array for (int cicli = 0; cicli < curva.length; cicli = cicli +1) { ellipse (curva[cicli], 5, 10, 10); } } Notiamo nello Sketch precedente che ad ogni inizio di ciclo viene pulito lo schermo attraverso l’istruzione “background (255);”. Se togliamo questa istruzione vedremo che le curve si sovrapporranno progressivamente andando a formare dopo diversi secondi un intero spicchio nero. Le ultime sezioni bianche che rimangono sono i processing guida introduttiva alla programmazione visuale 46
  • 47. numeri compresi tra zero e 200 che non sono mai stati generati. Probabilisticamente potrebbero passare anche diversi minuti senza che la funzione random generi un numero. processing guida introduttiva alla programmazione visuale 47
  • 48. Terza Parte Il testo Processing, come tutti i linguaggi di programmazione, permette di gestire il testo. I due comandi più importanti sono: char (); String (); Qesti due comandi sono in realtà due nuove tipi di variabili. La variabile di tipo “char” può contenere un unico carattere mentre la variabile di tipo “String” può contenere intere parole o frasi. Per assegnare un carattere a una variabile si scrive: char carattere = 'F'; In questo modo la lettera “F” viene memorizzata nella variabile “carattere”. Per assegnare una parole o una frase a una variabile si scrive: String testolungo = “manuale di Processing”; Da notare che “String” inizia con la lettera grande mentre “char” inizia con la lettera piccola. Da ricordare che i comandi di Processing debbono essere scritti tenendo conto anche di maiuscole e minuscole. Inoltre da notare che l’istruzione Char richiede gli apici (‘) per evidenziare il carattere mentre l’istruzione String richiede le virgolette (“). String può contenere anche testi lunghi un inico carattere. Nell’informatica esiste una tabella di corrispondenza tra i caratteri e i numeri. Praticamente ogni lettera dell’alfabeto è stata classificata con un numero in modo sequenziale. Questa tabella di corrispondenza si chiama ASCII e ad esempio la lettera A corrisponde al numero 65. La lettera B corrisponde al numero 66 e così via. Questa tabella di corrispondenza è indispensabile poichè senza di essa il computer (che ragiona per numeri) non potrebbe elaborare i testi. Le variabili di tipo “char”, essendo lunghe un unico carattere, possono essere ricondotte ai numeri e viceversa. Se ad esempio scriviamo: processing guida introduttiva alla programmazione visuale 48
  • 49. char carattere = ‘F’; int numero = carattere; La variabile “carattere” viene riempita con il valore “F”, poi con la seconda istruzione la variabile “numero” viene riempita con il numero corrispondente alla lettera F (70) secondo il codice ASCII. Questa operazione di conversione bidirezionale dei numeri in lettere e delle lettere in numeri è possibile solamente attraverso l’istruzione “char”. Con l’istruzione “String” essendo essa potenzialmente associata a testi più lunghi di una lettera ciò non è possibile. Attraverso l’espressione “char ()” possiamo richiamare direttabente il codice ASCII del carattere. Ad esempio se scriviamo: char lettera = char(70); Otteniamo che la variabile “lettera” viene associata con la lettera “F” (avente come codice ASCII il numero 70). L’istruzione “String” permette di fare operazioni sul testo. Se ad esempio associamo due variabili a due diverse parole, successivamente possiamo attaccare (sommare) le due parole. String prima = “Manuale di “; String seconda = “Processing”; String somma = prima + seconda; La variabile “somma” avrà come risultato “Manuale di Processing”. Da notare che dopo l’espressione “Manuale di” è stato lasciato appositamente uno spazio in modo che esso risulta presente nella somma delle due variabili. Il modo più velore per vedere il risultato di queste operazioni sule variabili testuali (ma anche per quelle numeriche) è l’uso dell’istruzione “println(somma);” Questa istruzione “println” mostra un valore nella finestra della console. La stessa finestra dell’ambiente di sviluppo dove ci appaiono gli errori. Questa finestra è utile quindi anche quando si sta lavorando ad un programma e si voglieno controllare dei valori intermedi e temporanei di alcune variabili. Caratteri sullo schermo Processing utilizza i font che sono stati precedentemente dichiarati. A differenza dei normali programmi di scrittura, dove troviamo il menù a tendoina con tutti i font disponibili, Processing, essendo un processing guida introduttiva alla programmazione visuale 49
  • 50. ambiente di sviluppo permette di utilizzare qualunque font che sia stato precedentemente impostato. Infatti Processing utilizza solamente tipi di carattere in formato VLW. Quando all’interno di uno Sketch sviluppato in Processing intendiamo utilizzare un font dobbiamo prima di tutto importare il font stesso attraverso il “Menù Tool” comando “Create Font”. Dando questo comando si apre una finestra nella quale compare la lista dei caratteri installati nel proprio computer. Si seleziona il carattere e la relativa dimensione che si vuole importare e cliccando su OK verrà automaticamente creato un file che poi potrà essere richiamato all’interno dello Sketch. Se ad esempio vogliamo utilizzare il font Courier nella dimensione 12 all’interno del nostro Sketch dopo avere generato il file dovremo richiamare un file di questo nome: “Courier-12.vlw”. Ecco uno Sketch: size (320, 240); background (255); // Inizializzo la variabile PFont carattere; // Carico il font nello Sketch carattere = loadFont("Courier-12.vlw"); // Stabilisco il font che sto per usare textFont(carattere); fill(0); // Scrivo il testo text("Manuale di Processing", 30, 100); Con “PFont” viene inizializzata una variabile che conterrà il nome del font stesso. Con “carattere = loadFont("Courier-12.vlw");” carico nello Sketch il font che intendo utilizzare e ovvimente potrei carirarne anche più di uno. Poi successivamente, quando starò per utilizzare il font, dichiaro il suo uso con “textFont(carattere);” e con “fill (0);” stabilisco che il carattere sarà di colore nero. Con l’istruzione “text” dichiariamo il testo che vogliamo scrivere (potremmo in alernativa mettere il nome di una variabile String) in seguito troviamo le coordinate X,Y dove comparirà il testo. Nel seguente Sketch abbiamo la situazione del precedente con l’unica differenza che attraverso l’istruzione “textSize(18);” il testo avrà una dimensione diversa da quella importata. processing guida introduttiva alla programmazione visuale 50
  • 51. size (320, 240); background (255); PFont carattere; carattere = loadFont("Courier-12.vlw"); textFont(carattere); textSize(18); fill(0); text("Manuale di Processing", 30, 100); Questa operazione di ingrandimento rappresenta un degradamento della qualità del carattere che risulterà sgranato tanto più sarà stato ingrandito. Infatti atttaverso l’azione di importazione del carattere abbiamo importato delle immagini bitmap (pixel per pixel) del font. Qualitativamente è quindi consigliabile importare i caratteri in tutte le dimensioni che si vorranno utilizzare. Il seguente Sketch è invece un semplice esempio di animazione di un testo. Si tratta all’incirca della somma dello Sketch precedente e dell Sketch utilizzato nelle pagine precedenti per animare un punto facendolo scorrere da sinistra a destra: void setup () { size (320, 240); } int intervallo = 0; void draw (){ background (255); PFont carattere; carattere = loadFont("Courier-12.vlw"); frameRate (10); textFont(carattere); textSize(12); fill(0); text("ciao a tutti", intervallo, 120); intervallo = intervallo + 1; } Lavorare con le Stringhe Processing permette di lavorare con le stringhe attraverso delle apposite istruzioni. Se ad esempio abbiamo la variabile “testolungo” associata ad una string: processing guida introduttiva alla programmazione visuale 51
  • 52. String testolungo = “manuale di Processing”; Possiamo misurare la lunghezza della stringa attraverso l’istruzione lunghezza = testolungo.length (); Dove lunghezza sarà una variabile di tipo “int” e in questo caso restituirà il numero “21”, ossia la lunghezza del testo “manuale di Processing” inclusi gli spazi tra una parola e l’altra. Mentre con la linea di comando: char iniziale = (testolungo.charAt(0)); Trasferisce il primo carattere (indicato con la posizione 0) della variabile “testolungo” nella variabile iniziale. Pertanto charAt(1) restituirà la “a” di “manuale” mentre il numero 6 ci darà la lettera “e”. Il numero 20 la lettera “g” di “Processing”. Attraverso l’istruzione substring (); possiamo invece prendere delle parti di una scringa ed associarle ad un’altra variabile (oppore stamparle...). string pezzo = testolungo.substring(2,6); Con questa linea di istruzione abbiamo trasferito in una nuova variabile “pezzo” tutte le lettere comprese tra la posizione 2 e la posizione 6 esclusa della variabile “testolungo”. In pratica abbiamo trasferito “nual” nella variabile pezzo. Il seguente Sketch produce una linea la cui lunghezza è inversamente legata alla lunghezza di un testo associato ad una variabile di tipo “String”. size (320, 240); String testolungo = "Manuale di Processing" ; // misuro la lunghezza di testolungo int lunghezza = testolungo.length (); // memorizzo il primo carattere // nella variabile “iniziale” char iniziale = (testolungo.charAt(0)); //produco una linea //usando la lunghezza line (lunghezza, lunghezza, 100, 100); processing guida introduttiva alla programmazione visuale 52
  • 53. Notiamo che il primo punto della linea è legato alla variabile “lunghezza” che abbiamo utilizzato per misurale la lunghezza del testo “manuale di Processing”. Aggiungesto altre parole al testo “manuale di Processing” e mandando in RUN lo Sketch vediamo che la linea tende progressivamente ad accorciarsi. processing guida introduttiva alla programmazione visuale 53
  • 54. Quarta Parte Grafica e Movimenti più complessi Processing è un software specializzato per la grafica e le animazioni. Tutte le istruzioni che abbiamo visto fino a questo punto ci hanno permesso di comprendere i principi fondamentali della computergrafica bidimensionale. Le forme che abbiamo disegnato fino ad ora sono relativamente semplici. Abbiamo visto con le curve di Bezier come sia possibile disegnare qualunque tipo di curva utilizzando 4 paramentri. Vediamo ora prima di tutto come animare le forme grafiche. In realtà abbiamo già visto come sia possibile, attraverso l’uso dei contatori e la pulizia dello schermo , animare curve e punti. Processing ci viene incontro in queste funzionalità di animazioni attraverso tre funzioni di animazione: translate (); rotate (); scale (); Attraverso queste tre semplici istruzioni possiamo applicare degli effetti graficamente complessi a tutte le immagini presenti all’interno del nostro Sketch. Sappiamo che scrivendo queste due istruzioni: size (320, 240); line(10, 20, 100, 120); otteniamo una linea che attraverso lo schermo. Attraverso l’istruzione “translate();” abbiamo la possibilità di traslare la linea sulle coordinate X e Y. Infatti se scriviamo: size (320, 240); translate(100, 0); line(10, 20, 100, 120); succede che la linea, a differenza del precedente Sketch, avrà delle cordinate traslate di 100 pixel sull’asse delle X. Le nuove coordinate della linea saranno: (110, 20, 200, 120). I due valori X dei due punti sono stati incrementati di 100 pixel. processing guida introduttiva alla programmazione visuale 54
  • 55. Ecco il risultato aritmetico dell’istruzione: line (10 + 100, 20 + 0, 100 + 100, 120 + 0); Ovviamente possiamo traslare sia le coordinate X che le Y, ecco un esempio: size (320, 240); translate(100, 25); line(10, 20, 100, 120); La linea disegnata sullo schermo avrà le seguenti coordinate: line (110, 45, 200, 145); L’istruzione traslate è attiva per tutte le forme grafiche che appaino successivamente ad essa. Pertanto se tracciamo due linee dopo l’istruzione traslate otteniamo che tutte e due le linee saranno traslate. size (320, 240); translate(100, 25); line (10, 20, 100, 120); line (20, 40, 200, 100); Mandando in RUN lo Sketch vediamo che sia la prima che la seconda linea risultano traslate. Inoltre le traslazioni si sommano, pertanto se vogliamo ulteriormente traslare una linea dopo una prima traslazione sarà sufficiente inserire la nuova traslazione. size (320, 240); translate(100, 25); line (10, 20, 100, 120); translate(80, 15); line (20, 40, 200, 100); La seconda linea del precedente Sketch è traslata nelle sue coordinate di 180 (100+80) pixel sull’asse “X” e 40 pixel sull’asse “Y” (25+15). Mentre la prima linea risulta traslata solamente dei valori del primo comando traslate. processing guida introduttiva alla programmazione visuale 55
  • 56. Per ripristinare le condizioni originarie è sufficiente mettere in negativo i valori di traslate. Nel sequente Sketch le coordinate della seconda linea sono “normali”. size (320, 240); translate(100, 25); line (10, 20, 100, 120); translate(-100, -25); line (20, 40, 200, 100); Poichè la seconda istruzione “traslate” sottrae esattamente i valori della prima istruzione, la seconda linea avrà le coordinate: line (20, 40, 200, 100); Proprio come indicato nello Sketch stesso. Rotazione I principi della traslazione valgono anche nel caso della rotazione. Essi quindi sono validi finchè non intervenga un nuovo valore che si somma al precedente. Per capire l’unità di misura dela rotazione dobbiamo capire il concetto di radiante. Normalmente misuriamo i giri in gradi, quindi un giro completo è di 360 gradi mentre un giro di 180 gradi è mezzo giro. Una ruotazione ad angolo retto è una ruotazione di 90 gradi. I radianti sono legati alla costante matematica detta “Pi greco” “PI” o “π”. Il pi greco misura il rapporto tra una qualunque circonferenza di un cerchio e il suo relativo diametro. Questo rapporto è costante e viene sintetizzato in 3.14 anche se i decimali dopo la virgola sono infiniti. La corrispondenza tra i gradi e i radianti è molto semplice: - due radianti (2 * π) sono 360 gradi - un radiante (π) è 180 gradi - mezzo radiante (π/2) è 90 gradi In processing π si scrive PI. Il seguente Sketch mostra la ruotazione di una stessa linea di 90 gradi: size (240, 240); line(0, 0, 100, 0); rotate(PI/2); line(0, 0, 100, 0); processing guida introduttiva alla programmazione visuale 56
  • 57. Mandando in RUN lo Sketch lediamo una linea in alto orizzontale (la prima linea dello Sketch) e una seconda linea verticale che è la seconda linea dello Sketch. La seconda linea ha subito quindi una rotazione di 90 gradi in senso orario. Le dimensione dello schermo questa volta sono state impostate a (240, 240) al fine di facilitare la comprensione dei gradi. Osserviamo infatti una rotazione di 45 gradi: size (240, 240); line(0, 0, 240, 0); rotate(PI/4); line(0, 0, 240, 0); Vediamo che la seconda linea in questo caso è ruotata di 45 gradi e grazie al fatto che la finestra è quadrata possiamo osservare che essa traccia una pate della diagonale della finestra stessa. Di seguito vediamo tre linee. La prima non subisce alcuna ruotazione mentre la seconda subisce una ruotazione di 45 gradi (PI/4) e la terza ruota di 90 gradi (PI/4 + PI/4 = PI/2). size (240, 240); line(0, 0, 240, 0); rotate(PI/4); line(0, 0, 240, 0); rotate(PI/4); line(0, 0, 240, 0); La funzione di ruotazione funziona quindi come la funzione di traslazione. Per eliminare il suo effetto è sufficiente riproporre il valore in negativo: size (240, 240); line(0, 0, 240, 0); rotate(PI/4); line(0, 0, 240, 0); rotate(- PI/4); strokeWeight (5); line(0, 0, 200, 0); In questo caso la terza linea sembra scomparire mentre in realtà essa è perfettamente sovrapposta alla prima linea. Per questo motivo ho processing guida introduttiva alla programmazione visuale 57
  • 58. aumentato lo spessore della linea “strokeWeight (5);” inoltre ho leggermente accorciato la lua lunghezza in modo che si possa cogliere anche la prima linea. Infine per comprendere completamente il tipo di ruotazione che avviene mandiamo in RUN il seguente Sketch size (240, 240); ellipse (100, 0, 20, 20); rotate(PI/4); ellipse (100, 0, 20, 20); Vediamo anche in questo caso che il cerchio si sposta. Mentre se il cerchio ruotasse su se stesso non dovremmo vedere alcuno spostamento. In effetti con il comando rotate così come con il comando translate ciò che ruota non è l’oggetto bensì la finestra con tutto ciò che è disegnato al suo interno. Questa ruotazione fa perno sulla coordinata (0,0) dello schermo. Scala Per ingrandire o rimpiccolire un oggetto si utilizza l’istruzione scale ();. Il seguente Sketch mostra due cerchi dove il secondo cerchio è stato raddoppiato nelle sue dimensioni: size (240, 240); ellipse (100, 100, 20, 20); scale (2); ellipse (100, 100, 20, 20); Le coordinate del cerchio cambiano proprio perchè è la finestra che si raddoppia nella sua dimensione con tutti i suoi contenuti. Il seguente Sketch mostra tre cerchi. Il terzo cerchio ha le stesse proporzioni del primo ma ho modificato il riempimento e ridimensionato il raggio. size (240, 240); ellipse (100, 100, 20, 20); scale (2); ellipse (100, 100, 20, 20); scale (0.5); fill (100,20); processing guida introduttiva alla programmazione visuale 58
  • 59. ellipse (100, 100, 10, 10); Vediamo che attraverso l’istruzione “scale (0.5);” è stato diviso per due il precedente rapporto di ingrandimento “scale(2)”. In questo modo il rapporto finale è 0.5*2 cioè 1. Quest’ultimo Sketch ci mostra tre cerchio scalati ogni volta per due. Il terzo cerchio sarà quindi 4 volte (2*2) più grande del primo. size (240, 240); ellipse (50, 50, 20, 20); scale (2); ellipse (50, 50, 20, 20); scale (2); ellipse (50, 50, 20, 20); Da notare che anche la distanza tra il secondo e il terzo cerchio è doppia rispetto alla distanza tra il primo e il secondo cerchio. Infine notiamo che le tre funzionalità di modifica delle forme grafiche possono ovviamente essere utilizzate in modo combinato. size (240, 240); ellipse (50, 50, 20, 20); scale (2); ellipse (50, 50, 20, 20); translate (20, 0); ellipse (50, 50, 20, 20); Nel precedente Sketch i cerchio risulterà traslato di 20 pixel sull’asse delle X e ingrandito di due volte. Il secondo cerchio ha invece subito solamente l’ingrandimento ma non la traslazione. processing guida introduttiva alla programmazione visuale 59
  • 60. Quinta parte Arduino Arduino è una piattaforma open source per lo sviluppo e la progettazione di oggetti interattivi. Lo scopo principale di questa scheda è quella di dare la possibilità a sviluppatori e artisti di progettare prototipi letteralmente “giocando” con l’elettronica e sperimentando con sensori, attuatori e controller elettronici. Questa particolare ricerca nell’interazione tra il calcolatore e il mondo fisico è nota come “Physical Computing” ed era fino a pochi anni fa una disciplina conosciuta e utilizzata solo in campo ingegneristico, che richiedeva una conoscenza avanzata dell’elettrotecnica e del software. Questo livello di complessità ha tenuto per anni lontani gli ideatori, gli obbisti e gli artisti dalle infinite possibilità che l’elettronica può aprire nel mondo del design e dell’arte in generale. Lo scopo degli sviluppatori di Arduino è quello di fornire uno strumento semplice che permetta a chiunque di iniziare a costruire progetti interattivi in modo immediato ed economico. Grazie a questa semplicità di utilizzo e alla crescente diffusione, oggi Arduino oltre a risolvere numerosi problemi nello sviluppo e nella realizzazione di oggetti interattivi, è alla base di una nuova filosofia che cresce e si alimenta dal mondo dell’open source e dalla condivisione di conoscenze tipica della rete. Nel mondo anglosassone questo “modo di procedere” nello sviluppo è noto come “Tinkering”, una forma di deriva creativa guidata dall’immaginazione e dalla curiosità. Mentre il percorso di sviluppo ingegneristico classico presuppone una progettazione che procede in modo razionale dal punto A al punto B, il Tinkering presuppone il perdersi in questo percorso e scoprire un nuovo punto C. Tinkering significa in pratica trovare risultati curiosi provando e sbagliando procedimenti ignoti. processing guida introduttiva alla programmazione visuale 60
  • 61. Costruire senza le istruzioni, giocando con i fallimenti, non preoccupandosi del modo giusto o sbagliato di fare le cose. Uno dei modi migliori di utilizzare questo processo creativo è riutilizzare tecnologie esistenti, smontare vecchi apparecchi elettronici e usarne parti interessanti sfruttandole per utilizzi lontani da quelli per cui erano state progettate. Questo approccio spontaneo e casuale è alla base di alcune nuove forme d’arte come il Circuit Bending: un genere musicale suonato con vecchi strumenti giocattolo elettronici, smontati e modificati per creare suoni completamente diversi da quelli pensati dal costruttore originario. Arduino insomma rappresenta oggi una nuova ottica con cui guardare la tencologia che ci circonda, sviluppare nuove funzioni per strumenti vecchi ed esplorare nuove possibilità senza il bisogno di perdersi in anni di studi ma semplicemente giocando con ciò che già abbiamo a portata di mano sfruttando l’istinto di ogni bambino... smontare i giocattoli per vedere cosa c’è dentro. L’Hardware: Arduino è una scheda composta principalmente da un processore e una serie di ingressi e uscite sia digitali che analogici, alimentabile sia via USB che tramite un alimentatore esterno. processing guida introduttiva alla programmazione visuale 61
  • 62. Il Software: Il processore di Arduino è programmabile attraverso un ambiente di sviluppo(IDE) basato su Processing. Tutto il software necessario all’utilizzo di Arduino oltre a svariati esempi di codice è scaricabile gratuitamente dal sito www.arduino.cc Una volta scritto il programma nell’editor principale (proprio come un programma in Processing) va controllata la sua correttezza, premendo verify, se il codice è scritto correttamente apparirà il messaggio Done compiling, a questo punto é possibile caricare il programma nel processore di Arduino. Premendo il bottone reset su Arduino si hanno 6 secondi per premere Upload to I/O board nella parte alte dell’IDE. Questo procedimento invia il programma alla scheda, lo salva nella sua memoria e lo esegue automaticamente. processing guida introduttiva alla programmazione visuale 62
  • 63. La BreadBoard Prima che il vostro circuito funzioni perfettamente ci sarà bisogno di vari tentativi e saldare diversi tentativi su una piastra è un lavoro lungo e dispendioso. L’equivalente elettronico dello schizzo iniziale di un progetto fatto su un foglio di carta è la BreadBoard. Si tratta in pratica di una piastra di plastica piena di fori ognuno dei quali contiene un contatto. Quando si mette un componente in uno di questi fori si crea un contatto elettrico con tutti gli altri fori della stessa colonna verticale. Le due coppie di linee di fori in alto e in basso della Breadboard (solitamente colorate di rosso e blu e con il segno+ e -) sono invece collegate in orizzontale e sono usate per portare l’alimentazione in tutta la piastra. processing guida introduttiva alla programmazione visuale 63