You are on page 1of 105

Getting

Started
with
Processing

Casey Reas e Ben Fry


Getting Started With Processing
Casey Reas Ben Fry

Apprendi la programmazione al computer nel modo pi semplice con Processing, un semplice


linguaggio che ti permette di usare codice per creare disegni, animazioni, e grafiche interattive.
Solitamente i corsi di programmazione iniziano con la teoria, ma questo libro ti permette di saltare
direttamente alla creazione di progetti creativi e divertenti.
l'ideale per chiunque voglia imparare la programmazione, e sar utile come semplice introduzione
alla grafica per coloro che hanno gi abilit programmative.

Scritto dai fondatori di Processing, questo libro ti accompagna attraverso il processo di


apprendimento un passo alla volta per aiutarti ad afferrare i concetti chiave della programmazione.
Entra a far parte delle migliaia di hobbisti, studenti e professionisti che hanno scoperto questa
piattaforma di educazione libera e gratuita.

>>impara velocemente le basi della programmazione, dalle variabili agli oggetti.


>>comprendi i concetti chiave della computer graphic
>>conosci l'ambiente di sviluppo di Processing
>>Crea grafiche interattive con progetti semplici da seguire
>>Usa il prototipo di piattaforma open-source Arduino per controllare la grafica di Processing

Casey Reas professore al dipartimento di Design Media Arts alla UCLA ed laureato al MIT
media laboratory. Il software di Reas stato presentato in numerose mostre solistiche e di gruppo
negli Stati Uniti, in Europa e in Asia.

Ben Fry designer, programmatore e autore con sede a Cambridge,nel Massachussetts,ed ha


ricevuto la sua laurea di dottorato dal MIT Media Laboratory. Ha lavorato con Casey Reas allo
sviluppo di Processing,che ha vinto un Golden Nica dal Prix Ars Electronica nel 2005.

Elogi Anticipati per Getting Started with Processing


Creare un programma per il computer che sia cos semplice da accendere e scrivere una o due
righe di codice per poter dire ciao. Ora possiede un manuale di circa 500 pagine e un'intera
comunit. Questo piccolo libro di Ben e Casey ti permette di disegnare attraverso il computer linee,
triangoli e cerchi in pochi minuti.
Hanno reso possibile la creazione di programmi al computer in modo umano , e questo non cosa
da poco.
John Maeda
. Presidente della Rhode Island School of Design

Getting Started with Processing non soltanto un modo chiaro di introdurre le basi della
programmazione divertente! Pu sembrare quasi un testo per progredire nell'attivit
programmativa. Potrai anche decidere di comprarlo anche se non sei mai stato interessato alla
programmazione, perch presto lo diventerai! .

Mark Allen
Fondatore e Direttore del Machine Project
Questo un eccellente inizio per coloro che vogliono affondare i loro passi nella programmazione
grafica . Il suo metodo dell' imparare facendo stato pensato in particolar modo per gli artisti e i
designer che molto spesso sono posti al di fuori dai primi approcci alla teoria tradizionale. Il prezzo
del libro ed il fatto che l'ambiente di Processing open source, ne fanno un'ottima scelta per gli
studenti.

-Gillian Crampton Smith


Fondazione Venezia Professor of Design, IUAV University of Venice

Processing ha cambiato radicalmente il modo di insegnare programmazione ed uno dei maggiori


fattori del successo di Arduino.

Massimo Banzi
Cofondatore di Arduino

Casey Reas e Ben Fry si sono battuti per l'entusiasmante energia della programmazione creativa in
Getting Started in Processing, una guida pratica per creare disegni e grafiche interattive basate sul
codice. Reas e Fry sono chiari e diretti ma come artisti non sono spaventati dall'essere un po'
eccentrici e fuori dalle righe. Questo quello che rende potente il loro unico metodo di
insegnamento .

Holly Willis
Direttore della Academic Programs, Institute for
Multimedia Literacy, School of Cinematic Arts,
USC
Prefazione

Abbiamo creato Processing per rendere pi facile la programmazione di grafica interattiva.


Eravamo frustrati da quanto fosse difficoltoso lo scrivere questo tipo di software con i linguaggi di
programmazione che usavamo di solito ( C++ e Java ) e ci siamo ispirati alla semplicit che era
propria dei linguaggi della nostra infanzia ( Logo e BASIC ) . La nostra principale fonte di
ispirazione Design By Numbers (DBN), un linguaggio creato dal nostro consulente di ricerca,
John Maeda, che al momento stiamo sostenendo ed insegnando.

Processing nacque nella primavera del 2001, come una sessione di brainstorming su un foglio di
carta. Il nostro obiettivo era trovare un modo di fare sketch o prototipi sulla tipologia di software a
cui stavamo lavorando, il quale era quasi sempre a pieno schermo ed interattivo.
Eravamo in cerca di un modo migliore per collaudare facilmente le nostre idee con il codice,
piuttosto che parlarne solamente o spenderci troppo tempo programmandolo in C++ .
Un altro nostro obiettivo era quello di creare un linguaggio per insegnare a studenti di arte e design
come programmare e per dare agli studenti pi tecnici un modo semplice per lavorare con la
grafica.
Questa combinazione un punto di partenza positivo dal modo di programmare insegnato di solito.
Noi iniziamo con il focalizzarci sulla grafica e l'interazione piuttosto che sulle strutture dati e
l'output di testo della console.

Processing ha vissuto una lunga infanzia; Era un software in fase alpha dall'agosto 2002 fino
all'aprile 2005, e poi in beta pubblico fino al novembre del 2008.
Durante questo lasso di tempo, fu usato continuamente nelle classi di studenti e da migliaia di
persone in tutto il mondo.
Il linguaggio,l'ambiente software, e la pedagogia intorno al progetto furono revisionati in
continuazione in questi anni. Molte delle nostre decisioni originali sul linguaggio furono rinforzate
e molte cambiate. Sviluppammo un sistema di estensione del software chiamato librerie , che ha
permesso alle persone di espandere Processing in direzioni impreviste e sorprendenti.
(Ci sono ora pi di 100 librerie.)
Il 29 novembre 2008 lanciammo la versione 1.0 del software.
Dopo sette anni di lavoro, il lancio della 1.0 significa stabilit per il linguaggio.

Ora, nove anni dopo le sue origini, Processing cresciuto al di l dei suoi obiettivi iniziali, e noi
abbiamo imparato come pu essere utile in altri contesti.
Di conseguenza questo libro scritto per un nuovo pubblico programmatori occasionali, hobbisti,
e chiunque voglia esplorare cosa Processing pu fare senza sentirsi perduto nei dettagli di un
enorme manuale. Questo libro solo il punto d'inizio.

Mentre noi (Casey e Ben) siamo stati la guida della nave di Processing attraverso le acque negli
ultimi nove anni, non si pu non riconoscere che Processing la fatica di una comunit.
Dallo scrivere librerie che estendono il software al pubblicare online codice e aiutare altri
nell'apprendimento, la comunit di persone che utilizzano Processing lo ha spinto molto lontano dal
suo concetto iniziale. Senza questo sforzo di gruppo, Processing non potrebbe essere ci che oggi.
COME QUESTO LIBRO ORGANIZZATO

I capitoli in questo libro sono organizzati come segue:

>>Capitolo 1, Hello . Conosci Processing


>>Capitolo 2, Iniziare a scrivere codice . Crea il tuo primo programma di Processing
>>Capitolo 3, Disegnare Definisci e disegna semplici forme
>>Capitolo 4 , Variabili Immagazzina,modifica e riutilizza i dati
>>Capitolo 5, Risposta Controlla ed influenza i programmi con il mouse e la tastiera
>>Capitolo 6, Media Carica e visualizza media, incluse immagini, font e file vettoriali.
>>Capitolo 7, Movimento Muovi e crea coreografie con le forme
>>Capitolo 8, Funzioni Costruisci nuovi moduli di codice
>>Capitolo 9, Oggetti Crea moduli di codice che combinano variabili e funzioni.
>>Capitolo 10, Arrays Semplifica il lavoro con liste di variabili.
>>Capitolo 11, Estendere Apprendi le funzionalit 3D, l'esportazione di immagini, e la lettura di
dati con la scheda Arduino.

Per chi questo libro


Questo libro scritto per le persone che desiderano un'introduzione semplice e concisa alla
programmazione, per chi vuole creare immagini e semplici programmi interattivi.
per coloro che vogliono una spinta per comprendere le migliaia di esempi gratuiti di codice di
Processing e il materiale dei riferimenti disponibile online. Getting Started with Processing non un
manuale di programmazione;
Come il titolo suggerisce ti permetter di avere un punto di partenza.
per adolescenti,hobbisti, nonni, e chiunque altro sia tra di loro.

Convenzioni usate in questo libro


In questo libro sono usate le seguenti convenzioni tipografiche:

>> Corsivo: usato per indicare nuovi termini e nomi di file, cos come all'interno di paragrafi
usato per riferirsi ad elementi del programma cos come ai nomi di funzioni e variabili, tipologie di
dati, e parole chiave.
>> constant width (carattere monospaziato): usato per elenchi di programma.

NOTA: questo tipo di paragrafo indica una nota generica

Usare gli Esempi di Codice


Questo libro qui per aiutarti a fare il tuo lavoro. In generale, puoi usare il codice in questo libro
nei tuoi programmi e nella tua documentazione. Non hai bisogno di contattarci per il permesso a
meno che non stai riproducendo una quantit significativa di codice.
Ad esempio, scrivere un programma che usa molte parti di codice da questo libro non richiede un
permesso. Vendere o distribuire un CD-ROM di esempi dai libri O'Reilly richiede un permesso.
Rispondere ad una domanda citando questo libro e e gli esempi di codice non richiede un permesso.
Incorporare un ammontare significativo di codice esemplificativo da questo libro nella
documentazione del tuo prodotto richiede un permesso.

Apprezziamo, ma non richiediamo, un'attribuzione. Un'attribuzione solitamente include il titolo,


l'autore, l'editore e l'ISBN. Ad esempio Getting Started with Processing, by Casey Reas and Ben
Fry. Copyright 2010 Casey Reas and Ben Fry, 978-1-449-37980-3

Se senti che il tuo utilizzo del codice esemplificativo va oltre l'uso corretto o il permesso dato in
questo libro, sentiti libero di contattarci a permissions@oreilly.com .

Come contattarci

Prego indirizzare commenti e domande riguardanti questo libro all'editore:

O'Reilly Media , Inc.


1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 ( in the United States or Canada)
707829-0515 ( international or local )
707-829-0104 ( fax)

Abbiamo una pagina web per questo libro, dove elenchiamo errata corrige, esempi, e ogni
informazione addizionale. Puoi accedere a questa pagina a:

>> http://oreilly.com/catalog/0636920000570

Per commentare o chiedere su questioni tecniche riguardo questo libro, mandare una email a:

>> bookquestions@oreilly.com

Per ulteriori informazioni riguardanti il nostro libro, le conferenze, i Resource Centers, e la rete
O'Reilly, visita il nostro sito web a:

>> http://oreilly.com

Riconoscimenti
Ringraziamo Brian Jepson per la sua grande energia, sostegno ed intuito.
Nancy Kotary, Rachel monaghan, e Sumita Mukherji che con pazienza hanno portato il libro alla
linea di arrivo.

Tom Sgouros per avere fatto un'accurata edizione del libro e David Humphrey per aver fornito una
recensione tecnica.

Non possiamo immaginare questo libro senza Getting Started with Arduino ( O'Reilly) di Massimo
Banzi. L'eccellente libro di Massimo stato il nostro prototipo.

Un piccolo gruppo di individui ha, per anni, contribuito a portare tempo essenziale ed energia a
Processing. Ringraziamo Florian Jenett per il suo web hacking e le eccellenti abilit di designer,
Andreas Schlegel per aver creato le infrastrutture per la costruzione e la documentazione delle
librerie, e Dan Shiffman per aver scritto straordinari esempi e gestito i tutorial on-line.
Nel corso del tempo, molti altri hanno contribuito allo stesso software di Processing, tra loro
Karsten Schmidt, Eric Jordan, and Jonathan Feinberg.
Il lavoro di PhiLho, Cedric e antiplastik,amministratori del forum Discourse, stato cruciale per
tenere aperto il dibattito.

Siamo stupiti dall'incredibile lavoro degli individui che scrivono librerie e condividono il loro
lavoro con la comunit. Grazie a tutti! Una annotazione speciale riservata per le librerie
GLGraphics e GSVideo di Andres Colubri, la libreria del suono Minim di Damien Di Fede e per gli
estesi ed ispiratori toxiclibs.

La release 1.0 di Processing stata supportata dall'universit di Miami e dalle Oblong Industries.
L'Armstrong Institute for Interactive Media Studies all'universit di Miami ha fondato l'Oxford
Project, una serie di workshop per lo sviluppo di Processing.
Questi workshop sono stati resi possibili grazie al duro lavoro di Ira Greenberg. Questi incontri di
quattro giorni ad Oxford, in Ohio e Pittsburgh,Pennsylvania, hanno abilitato il lancio di Processing
1.0 nel Novembre 2008 .
Le Oblong Industries hanno finanziato Ben Fry per sviluppare Processing nell'estate del 2008.
Ci fu essenziale per la release.

Questo libro nasce dalle lezioni di Processing alla UCLA. Chandler McWilliams stato
determinante nella definizione di queste classi. Casey ringrazia gli studenti universitari del
dipartimento di Design Media Arts alla UCLA per la loro energia ed entusiasmo. I suoi assistenti
sono stati grandi collaboratori nel definire come Processing andava insegnato.
Complimenti a Tatsuya Saito, John Houck, Tyler Adams, Aaron Siegel, Casey Alt, Andres Colubri,
Michael Kontopoulos, David Elliott, Christo Allegra, Pete Hawkes, e Lauren McCarthy.

Open Processing nato come luogo dove condividere il codice open-source di Processing.
Ringraziamo Sinan Ascioglu per questa incredibile risorsa comunitaria.

Processing.js un eccitante futuro per Processing ed il Web.


Ulteriori ringraziamenti sono per John Resig, Al MacDonald, David Humphrey, e il Seneca
College's Centre for Development of Open Technology ( CDOT ), Robert O'Rourke , e la Mozilla
Foundation.

Attraverso la fondazione della sthetics and Computation Group (1996-2002) e il MIT Media Lab ,
John Maeda ha reso tutto questo possibile.
1/Hello
Processing stato creato per scrivere software per la creazione di
immagini,animazioni ed interazioni. L'idea di scrivere una
singola riga di codice, e di far apparire un cerchio sullo schermo.
Aggiungere ancora poche linee di codice , ed il cerchio segue il
mouse.
Un'altra riga di codice, ed il cerchio cambia colore quando il
mouse viene premuto.
Noi chiamiamo questo sketching (abbozzare) con il codice.
Scrivi una riga, poi ne aggiungi un'altra, e poi un'altra
ancora,un'altra e cos via.
Il risultato che il programma viene creato un pezzo alla volta.
I corsi di programmazione di solito si focalizzano prima sulla struttura e sulla teoria.
Ogni cosa che sia visiva -un'interfaccia,un'animazione- considerata un dessert da gustare solo
dopo aver finito le verdure, di solito dopo diverse settimane di studio di algoritmi e metodi.
Attraverso gli anni abbiamo osservato molti amici provare a seguire corsi e ritirarsi dopo la prima
lezione o dopo una lunga, frustrante notte dopo la prima scadenza di compiti.
La curiosit iniziale che hanno avuto riguardo al lavoro al computer andava perduta perch non
hanno saputo trovare una connessione tra quello che imparavano inizialmente e ci che volevano
creare.

Processing offre una via per apprendere la programmazione attraverso la creazione di grafiche
interattive. Esistono diversi modi di insegnare il codice, ma gli studenti spesso trovano
incoraggiamento e motivazione immediata in un responso visivo.
La capacit di Processing di fornire questo feedback ne ha fatto un modo popolare di approcciare
alla programmazione, e la sua enfasi nelle immagini , nello sketching e nella comunit verr
presentata tra poche pagine.

Schizzare e creare Prototipi

Schizzare un modo di pensare ; giocoso e rapido.


L'obiettivo di base l'esplorazione di diverse idee in uno stretto spazio di tempo.
Nel nostro lavoro personale, di solito partiamo a schizzare su carta e poi trasferiamo il risultato nel
codice. Le idee per animazioni e interazioni sono di solito abbozzate come degli storyboard con
annotazioni. Dopo aver fatto diversi bozzetti del software, le idee migliori sono selezionate e
combinate in prototipi (Figura 1-1). E' un processo ciclico di creazione, analisi e miglioramento che
si muove avanti e indietro tra la carta e lo schermo.

Flessibilit

Come una cintura degli attrezzi del software, Processing composto di molteplici strumenti che
lavorano assieme in combinazioni differenti. Come risultato, pu essere usato per rapidi hacks o
per ricerche approfondite. Poich un programma di Processing pu avere sia la lunghezza di una
riga che di diverse migliaia, c' spazio per crescita e variazione . Pi di 100 librerie estendono
ulteriormente Processing in domini come suono, computer vision e digital fabrication (Figura 1-2).

Giganti
L'umanit ha creato immagini con i computer dal 1960, e c' molto da imparare da questo percorso
(Figura 1-3). Nella vita, noi tutti siamo sulle spalle di giganti, e i titani per Processing includono
pensatori cha vanno dal design, alla computer grafica, all'arte, all'architettura, alla statistica, e a tutto
il resto. Dai un'occhiata allo Sketchpad (1963) di Ivan Sutherland, al Dynabook (1968) di Alan Kay,
ed ai molti artisti caratterizzati in Artist and Computer di Ruth Leavitt (Harmony Books,1976).
Gli archivi della ACM SIGGRAPH offrono uno sguardo affascinante della storia della grafica e del
software.

Albero di Famiglia

Come i linguaggi umani, i linguaggi di programmazione appartengono a famiglie correlate.


Processing un dialetto di un linguaggio di programmazione chiamato Java;
La sintassi del linguaggio pressoch identica , ma Processing aggiunge funzioni personalizzate
correlate alla grafica e all'interazione (Figure 1-4).
Gli elementi grafici di Processing sono relazionati a PostScript (una fondazione di PDF) e OpenGL
(una specificazione della grafica 3D). A causa di queste funzioni condivise, imparare ad usare
Processing un primo passo per programmare in altri linguaggi e usare strumenti software
differenti.

Partecipa

Migliaia di persone usano Processing ogni giorno. Come loro, puoi scaricare Processing senza alcun
costo. Hai anche l'opzione di modificare il codice di Processing per soddisfare le tue necessit.
Processing un progetto FLOSS (cio, free/libre/open source software), e nello spirito della
comunit, ti incoraggiamo a partecipare attraverso la condivisione di progetti e conoscenza online a
Processing.org e ai principali siti di social network che ospitano i contenuti di Processing ( Figura
1-5). Questi siti hanno un link al sito web Processing.org.
2/Iniziare a scrivere codice
Per ottenere il massimo da questo libro, hai bisogno qualcosa in
pi che leggere solamente le parole.
Hai bisogno di fare esperimenti e di fare pratica .
Non puoi imparare a scrivere codice solo leggendo su di esso hai
bisogno di crearlo.
Per iniziare, scarica Processing e crea il tuo primo sketch.
Comincia con il visitare http://processing.org/download e selezionare la versione per Mac,
Windows o Linux, a seconda della macchina che possiedi. L'installazione su qualsiasi macchina
semplice:

>> Su Windows hai un file .zip. Fai doppio click su di esso e trascina la cartella in una posizione
all'interno del tuo hard disk. Potrebbe essere la cartella Programmi o semplicemente il desktop, ma
la cosa importante che la cartella processing dev'essere estratta dal file .zip. A questo punto fai
doppio click su processing.exe per iniziare.

>> La versione per Mac OS X un file disk image (.dmg). Trascina l'icona di Processing nella
cartella Applications. Se stai usando la macchina di qualcun altro e non puoi modificare la cartella
Applications, basta trascinare l'applicazione sul desktop. A questo punto fai doppio click sull'icona
di Processing per iniziare .

>> La versione per Linux un file .tar.gz , il quale dovrebbe essere familiare alla maggior parte
degli utenti Linux. Scarica il file nella tua home directory ,quindi apri una terminal window , e
digita:

tar xvfz processing-xxxx.tgz

(Sostituisci xxxx con il nome rimanente del file, il quale il numero della versione.) Questo creer
una cartella chiamata processing-1.0 o qualcosa di simile . Poi passa a questa directory:

cd processing-xxxx
ed eseguilo:

./processing

Con ogni probabilit,la finestra principale di Processing sar ora visibile ( Figura 2-1).
Il setup di ognuno differente, quindi se il programma non riesce a partire, oppure sei bloccato per
qualche altro motivo, visita la pagina di risoluzione problemi per possibili soluzioni:
http://wiki.processing.org/index.php/troubleshooting .

Il tuo Primo Programma

Adesso stai eseguendo il Processing Development Environment ( o PDE).


Non c' granch su di esso; l'area pi grande l'editor di testo , e nella parte superiore si trova una
fila di pulsanti; questa la barra degli strumenti (toolbar). Sotto l'editor si trova l'area dei messaggi
e sotto ancora la Console. L'Area Messaggi utilizzata per messaggi ad una riga , e la Console per
dettagli pi tecnici.

Esempio 2-1: Disegna un' ellisse


Nell'editor, digita quanto segue:

ellipse ( 50,50,80,80 );

Questa linea di codice significa disegna un'ellisse, con centro 50 pixel a partire da sinistra e 50
pixel a partire dall'alto, con una larghezza ed un'altezza di 80 pixel.
Clicca sul pulsante Esegui (Run) , che appare cos:

Se hai digitato ogni cosa correttamente, vedrai l'immagine dell'ellisse qui sopra.
Se non hai digitato correttamente, l'area messaggi diventer rossa e reclamer un errore.
Se ci accade, assicurati di aver copiato il codice di esempio correttamente: i numeri dovrebbero
esser contenuti tra le parentesi e tra di loro dovrebbero avere le virgole, e la riga dovrebbe finire con
un punto e virgola.

Una delle cose pi difficili di iniziare a programmare il bisogno di essere molto specifici con la
sintassi. Il software di Processing spesso non abbastanza furbo da capire cosa vuoi dire, e potrebbe
essere leggermente puntiglioso riguardo il posizionamento della punteggiatura.
Acquisterai maneggevolezza con un p di pratica.

Di seguito passeremo ad uno sketch leggermente pi stimolante.

Esempio 2-2: Creare Cerchi


Cancella il testo dell'ultimo esempio, e prova questo:

void setup(){
size(480,120);
smooth();
}
void draw(){
if (mousePressed){
fill(0);
} else {
fill(255);
}
ellipse(mouseX,mouseY,80,80);
}

Questo programma crea una finestra larga 480 pixel e alta 120 pixel, poi comincia a disegnare
cerchi bianchi alla posizione del mouse. Quando il pulsante del mouse premuto, il colore del
cerchio cambia e diventa nero. Approfondiremo in seguito nel dettaglio riguardo gli elementi di
questo programma.
Per adesso ,esegui il codice, muovi il mouse, e clicca per provarlo.

Visualizzare

Finora abbiamo trattato solo il pulsante Esegui, anche se probabilmente hai gi indovinato a cosa
serve il pulsante Stop situato a fianco.

Se non vuoi usarlo, puoi sempre utilizzare il menu sketch, il quale rivela la scorciatoia Ctrl-R (o
Cmd-R per il Mac) per Esegui. Al di sotto di Esegui nel menu sketch si trova Present, che libera il
resto dello schermo per mostrare solamente il tuo sketch:

Puoi anche usare Present dalla Toolbar tenendo premuto il tasto Shift mentre premi il pulsante Run.

Salvare

Il prossimo comando fondamentale Salva. la freccia che da verso il basso sulla barra degli
strumenti:

Puoi anche trovarla sotto il menu File. Come impostazione predefinita, i tuoi programmi sono
salvati nello sketchbook, che la cartella che li raccoglie per un facile accesso.
Cliccando il pulsante Open sulla toolbar ( la freccia che punta in alto) apparir una lista di tutti gli
sketch nel tuo sketchbook, oltre ad una lista di esempi che sono installati nel software di Processing:

sempre una buona idea salvare spesso i tuoi sketch. Quando provi soluzioni diverse, tienile
salvate con nomi differenti , cos che puoi sempre tornare indietro ad una versione precedente.
Ci particolarmente utile se qualcosa non va. Puoi anche vedere dove lo sketch collocato sul
disco, con Show Sketch Folder nel menu.

Puoi anche creare un nuovo sketch premendo il pulsante New sulla barra degli strumenti:

Questo prender il posto dello sketch nella finestra corrente con uno vuoto.
Tenendo premuto Shift mentre si preme il pulsante New verr creato un nuovo sketch nella sua
propria finestra , cos come selezionando File New. Il pulsante Open funziona allo stesso modo.

Condividi

Un altro punto importante di Processing la condivisione del tuo lavoro. Il pulsante Export sulla
toolbar:

raccoglier il tuo codice in un'unica cartella intitolata applet che pu essere caricata su un server
web (Figura 2-2). Dopo l'esportazione ,la cartella applet si aprir sul tuo desktop.
Il file PDE il file sorgente, il file JAR il programma, il file HTML la pagina web, e il file GIF
visualizzato sul browser web mentre il programma in caricamento. Fare doppio click sul file
index.html lancer il browser e mostrer il tuo sketch nella pagina web che ha creato.

NOTA : la cartella applet viene cancellata e ricreata ogni volta che userai il comando Esporta,
quindi assicurati di spostare la tua cartella da qualche altra parte prima di fare un qualsiasi
cambiamento al file HTML o qualsiasi altra cosa al suo interno.

Puoi anche trovare Export ,insieme a suo fratello Export to Application, sotto al menu File.
Export to Application crea un'applicazione a tua scelta per Mac, Windows, e/o Linux.
Questo un modo semplice di fare versioni autonome e doppio-cliccabili dei tuoi progetti (Figure
2-3).

Tenere premuto Shift mentre premi il pulsante Export sulla toolbar un altro modo di usare Export
to Application.

Esempi e Riferimenti
Imparare come programmare con Processing comporta l'esplorazione di una gran quantit di codice:
eseguire,modificare, manomettere e migliorare il codice fino a quando non si trasformato in
qualcosa di nuovo. Tenendo questo a mente, il download del software di Processing include dozzine
di esempi che dimostrano le differenti caratteristiche del software.
Per aprire un esempio, seleziona Examples dal menu File o clicca l'icona Open nel file PDE.
Gli esempi sono raggruppati in categorie basate sulle loro funzioni, come Form, Motion, and Image.
Trova un argomento interessante nella lista e prova un esempio.

Se vedi una parte del programma con cui non hai familiarit che colorata di arancione (questo
significa che una parte di Processing) , seleziona il suo nome , e clicca su Find in Reference dal
menu Help. Puoi anche cliccare con il tasto destro sul testo (o Ctrl-click per il Mac) e scegliere Find
in Reference dal menu che apparso.
Questo aprir i riferimenti riguardanti l'elemento del codice selezionato nel tuo browser. I
riferimenti sono disponibili inoltre online all'indirizzo http://www.processing.org/reference/.

Le Reference di Processing spiegano ogni elemento del codice con una descrizione ed esempi.
I programmi di riferimento sono molto pi brevi (solitamente quattro o cinque righe) e pi semplici
dei lunghi codici trovati nella cartella Examples. Raccomandiamo di tenere aperte le Reference
mentre stai leggendo questo libro e mentre stai programmando. Possono essere navigate per
argomento o in ordine alfabetico; solitamente la cosa pi veloce da fare una text search nella
finestra del browser.

Le Reference sono state scritte con in mente il principiante; Speriamo che siano chiari e
comprensibili. Siamo grati alle molte persone che hanno individuato gli errori durante gli anni e che
li hanno riportati. Se pensi di poter migliorare la voce di una Reference o hai trovato un errore ,
prego permettici di conoscerlo cliccando sul link in cima ad ogni pagina delle Reference.
3/Disegnare

Prima di tutto, disegnare sullo schermo di un computer come


lavorare su carta millimetrata.
Si inizia con un'accurata procedura tecnica, ma come vengono
introdotti nuovi concetti, il disegnare semplici forme con il
software si espande nell'animazione e nell'interazione.
Prima di fare questo salto, abbiamo bisogno di partire dall'inizio.
Lo schermo di un computer una griglia di elementi luminosi chiamati pixel. Ogni pixel ha una
posizione all'interno della griglia definita dalle proprie coordinate. In Processing, la coordinata X
la distanza dal bordo sinistro della finestra di visualizzazione e la coordinata Y la distanza dal
bordo superiore. Scriviamo le coordinate di un pixel in questo modo : (x,y).
Quindi,se lo schermo di 200x200 pixel, quello in alto a sinistra (0,0), il centro si trova a
(100,100), ed in basso a destra (199,199). Questi numeri potrebbero sembrare confusi; perch
andiamo da 0 a 199 invece di andare da 1 a 200? La risposta che nel codice, di solito iniziamo il
conteggio da 0 poich pi facile per i calcoli che ci troveremo ad affrontare pi tardi.

La finestra di visualizzazione (Display Windows) e le immagini all'interno di essa sono create


attraverso elementi di codice chiamati funzioni. Le funzioni sono i blocchi di costruzione base di un
programma di Processing. Il comportamento di una funzione definita dai suoi parametri.
Ad esempio, quasi ogni programma di Processing ha una funzione size( ) per fissare l'altezza e la
larghezza della finestra di visualizzazione. (se il tuo programma non ha una funzione size( ), la
dimensione stabilita a 100x100 pixel.)

Esempio 3-1: Disegnare una finestra


La funzione size( ) ha due parametri : il primo stabilisce la larghezza della finestra e il secondo
stabilisce l'altezza. Per disegnare una finestra che sia larga 800 pixel e alta 600 , scrivi:

size (800, 600);


Esegui questa linea di codice per vedere il risultato. Inserisci valori differenti per vedere le
possibilit. Prova numeri molto piccoli e numeri grandi quanto il tuo schermo.

Esempio 3-2: Disegnare un Punto


Per definire il colore di un singolo pixel nella finestra di visualizzazione, usiamo la funzione
point( ). Ha due parametri che definiscono la posizione : la coordinata X seguita dalla coordinata Y.
Per disegnare una piccola finestra ed un punto al centro dello schermo, con le coordinate (240,60),
digita:

size(480,120);
point(240,60);

Prova a scrivere un programma che inserisca un punto ad ogni angolo della finestra di
visualizzazione ed una al centro. Prova ad inserire i punti fianco a fianco per creare linee
orizzontali, verticali e diagonali.

Forme Base

Processing include un gruppo di funzioni per disegnare forme base ( vedi la Figura 3-1). Le forme
semplici come le linee possono essere combinate per creare forme pi complesse come una foglia o
un viso.

Per disegnare una singola linea, abbiamo bisogno di quattro parametri : due per la posizione di
partenza e due per il punto finale.

Esempio 3-3: Disegnare una Linea


Per disegnare una linea tra le coordinate (20,50) e (420,110), prova :

size (480, 120);


line (20, 50, 420, 110);

Esempio 3-4: Disegnare Forme Base


Seguendo questo modello, un triangolo richiede sei parametri e un quadrilatero ne richiede
otto (un paio per ogni punto):

size (480, 120)


quad ( 158, 55, 199, 14, 392, 66, 351, 107 );
triangle ( 347, 54, 392, 9, 392, 66 );
triangle ( 158, 55, 290, 91, 290, 112 );

Esempio 3-5: Disegnare un Rettangolo


Rettangoli ed ellissi sono entrambi definiti con quattro parametri: il primo e il secondo sono per le
coordinate X e Y dei punti di ancoraggi, il terzo per l'altezza e il quarto per la larghezza .
Per creare un rettangolo alle coordinate ( 180, 60) con una largezza di 220 pixel e un' altezza di 40,
usa la funzione rect( ) in questo modo:

size (480, 120);


rect (180, 60, 220, 40);

Esempio 3-6: Disegnare una Ellisse


Le coordinate X e Y per un rettangolo sono l'angolo in alto a sinistra , ma per una ellissi sono il
centro della forma . In questo esempio, nota che la coordinata Y per la prima ellisse situata fuori
dalla finestra. Gli oggetti possono essere disegnati parzialmente ( o interamente ) fuori dalla finestra
senza causare un errore:

size ( 480, 120 );


ellipse ( 278, -100, 400, 400);
ellipse ( 120, 100, 110, 110);
ellipse ( 412, 60, 18, 18);

Processing non ha funzioni separate per creare quadrati e cerchi. Per fare queste forme, usa gli stessi
valori dei parametri di altezza e larghezza per ellipse( ) e rect( ) .

Esempio 3-7: Disegnare una Parte di una Ellisse


La funzione arc( ) disegna una parte di una ellisse:

size( 480, 120);


arc (90,60,80,80,0,HALF_PI);
arc (190,60,80,80,0,PI+HALF_PI);
arc (290,60,80,80,PI,TWO_PI+HALF_PI);
arc (390,60,80,80,QUARTER_PI,PI+QUARTER_PI);

Il primo e il secondo parametro indicano la posizione, il terzo e il quarto indicano l'altezza e la


larghezza. Il quinto parametro indica l'angolo da dove far partire l'arco, e il sesto indica l'angolo
dove fermarlo. Gli angoli sono indicati in radianti invece che in gradi. I radianti sono misurazioni di
angoli basati sul valore del PI ( 3.14159 ).
La figura 3-2 mostra come i due sono in relazione. Come si vede da questo esempio i quattro valori
dei radianti sono usati cos frequentemente da prendere dei nomi speciali come parte integrante di
Processing. I valori PI, QUARTER_PI, HALF_PI, e TWO_PI possono essere usati per riprendere i
valori in radianti di 180 , 45, 90, e 360 .

Esempio 3-8: Disegnare in Gradi


Se tu preferisci usare delle misurazioni in gradi, puoi convertirli in radianti con la funzione
radians( ) .
Questa funzione prende un angolo in gradi e lo trasforma nel corrispondente valore in radianti.
L'esempio seguente lo stesso dell'esempio 3-7, ma questo usa la funzione radians( ) per definire il
valore di inizio e di fine in gradi:

size ( 480,120 );
arc ( 90, 60, 80, 80, 0, radians(90));
arc ( 190, 60, 80, 80, 0, radians(270));
arc ( 290, 60, 80, 80, radians(180),radians(450));
arc ( 390, 60, 80, 80, radians(45), radians(225));

Disegnare in Ordine
Quando un programma viene eseguito, il computer comincia dalla cima e legge ogni riga del codice
fino a raggiungere l'ultima linea e poi si ferma.
Se vuoi una forma che sia disegnata in cima alle altre forme, dev'essere scritta di seguito alle altre
nel codice.

Esempio 3-9: Controllare l'Ordine di Disegno

size (480, 120);


ellipse(140, 0, 190, 190);
//il rettangolo viene disegnato sopra l'ellisse
//perch viene dopo nel codice
rect (160, 30, 260, 20);

Esempio 3-10: Metterlo al Contrario


Modifica l'esempio 3-9 invertendo l'ordine di rect( ) ed ellipse( ) per vedere il cerchio sopra il
rettangolo:

size(480,120);
rect(160, 30, 260, 20 );
//L'ellisse viene disegnata sopra il rettangolo
// poich viene scritta successivamente nel codice
ellipse(140, 0, 190, 190);

Puoi pensarlo come dipingere con un pennello o come fare un collage. L'ultimo elemento che
aggiungi quello che si vede in cima.

Propriet delle Forme


Le propriet delle forme pi fondamentali e utili sono lo spessore del contorno e l'anti-aliasing,
chiamato anche smoothing.

Esempio 3-11: Disegnare Linee Smussate.


La funzione smooth( ) smussa i bordi delle linee disegnate sullo schermo fondendo i margini con i
valori dei pixel nelle vicinanze. Al contrario, se lo smoothing gi attivato, la funzione noSmooth( )
lo render inattivo:

size(480,120);
smooth( ); // attiva lo smoothing
ellipse ( 140, 60, 90, 90 );
noSmooth ( ); // disattiva lo smoothing
ellipse ( 240, 60, 90, 90);

NOTA: Qualche implementazione di Processing (come la versione per JavaScript) smusser sempre
le forme; altre potrebbero non supportare del tutto questa funzione. In alcune situazioni, non
possibile abilitare e disabilitare lo smoothing nello stesso passaggio mediante draw( ). Vedi le
referenze riguardanti lo smooth( ) per maggiori dettagli.

Esempio 3-12: Impostare lo Spessore del Contorno


La larghezza standard per il contorno di un singolo pixel, ma pu essere cambiata con la funzione
strokeWeight( ). L'unico parametro per strokeWeight( ) regola la larghezza delle linee disegnate:

size(480, 120);
smooth();
ellipse(75, 60, 90, 90);
strokeWeight(8); // Spessore del contorno a 8 pixel
ellipse(175, 60, 90, 90);
ellipse(279, 60, 90, 90);
strokeWeight(20); // Spessore del contorno a 20 pixel
ellipse(389, 60, 90, 90);

Esempio 3-13: Stabilire gli Attributi del Contorno


La funzione strokeJoin( ) cambia il modo con cui le linee sono unite (cio come appaiono gli
angoli), e la funzione strokeCap( ) modifica il modo in cui le linee vengono disegnate al loro punto
di partenza e alla loro fine .

size(480, 120);
smooth();
strokeWeight(12);
strokeJoin(ROUND); // Arrotonda lo spessore degli angoli
rect(40, 25, 70, 70);
strokeJoin(BEVEL); // Smussa lo spessore degli angoli
rect(140, 25, 70, 70);
strokeCap(SQUARE); // Squadra le terminazioni delle linee
line(270, 25, 340, 95);
strokeCap(ROUND); // Arrotonda le terminazioni delle linee
line(350, 25, 420, 95);

La collocazione di forme come rect( ) ed ellipse( ) controllato con le funzioni rectMode( ) e


ellipseMode( ). Controlla le Reference (Help Reference) per vedere gli esempi e come
posizionare i rettangoli in riferimento al loro centro (invece che partendo dall'angolo in alto a
sinistra), o come disegnare le ellissi dall'angolo in alto a sinistra come i rettangoli.

Quando ognuno di questi attributi stabilito, tutte le forme disegnate di seguito vengono
condizionate. Come dimostrazione, nota come nell' Esempio 3-12 il secondo ed il terzo cerchio
abbiano entrambi lo stesso spessore del contorno, sebbene la larghezza impostata solo una volta
prima che entrambi siano disegnati.

Colore
Tutte le forme fino a questo momento sono state riempite di bianco con i lineamenti neri, e lo
sfondo della finestra di visualizzazione era regolata su un grigio chiaro. Per cambiarli, usa le
funzioni background( ), fill( ) e stroke( ). I valori dei parametri sono in una gamma che va da 0 a
255, dove 255 bianco , 128 grigio medio, e 0 nero. La figura 3-3 ti mostra come i valori da 0 a
255 scalano a differenti livelli di grigio.

Esempio 3-14: Dipingere con i Grigi


Questo esempio mostra tre differenti valori di grigio su uno sfondo grigio:

size(480, 120);
smooth();
background(0); // Nero
fill(204); // Grigio chiaro
ellipse(132, 82, 200, 200); // Cerchio grigio chiaro
fill(153); // Grigio medio
ellipse(228, -16, 200, 200); // Cerchio grigio medio
fill(102); // Grigio scuro
ellipse(268, 118, 200, 200); // Cerchio grigio scuro

Esempio 3-15: Controlla il Riempimento ed il Contorno


Puoi disabilitare il contorno cos che non ci siano linee esterne con noStroke( ) e puoi disabilitare il
riempimento della forma con noFill( ) :

size(480, 120);
smooth();
fill(153); // Grigio medio
ellipse(132, 82, 200, 200); // Cerchio grigio
noFill(); // Disattiva il riempimento
ellipse(228, -16, 200, 200); // Profilo del cerchio
noStroke(); // Disattiva il contorno
ellipse(268, 118, 200, 200); // Non disegna nulla!

Stai attento a non disabilitare allo stesso tempo contorno e riempimento, come abbiamo fatto
nell'esempio precedente, altrimenti non verr disegnato nulla sullo schermo.

Esempio 3-16: Disegnare con i Colori


Per muoverti tra i valori della scala di grigi, usa tre parametri per specificare le componenti di rosso,
verde e blu di un colore . Poich questo libro stampato in nero e bianco, vedrai qui solo valori di
grigio. Esegui il codice con Processing per rivelare i colori:

size(480, 120);
noStroke();
smooth();
background(0, 26, 51); // Colore blu scuro
fill(255, 0, 0); // Colore rosso
ellipse(132, 82, 200, 200); // Cerchio rosso
fill(0, 255, 0); // Colore Verde
ellipse(228, -16, 200, 200); // Cerchio verde
fill(0, 0, 255); // Colore blu
ellipse(268, 118, 200, 200); // Cerchio blu

Questo denominato colore RGB, il quale deriva dal modo in cui i computer definiscono i colori
sullo schermo. I tre numeri riportano i valori di rosso, verde e blu e la loro gamma da 0 a 255, nello
stesso modo dei valori di grigio. Usare i colori RGB non cos intuitivo, quindi per scegliere i
colori , usa Tools Color Selector, che mostra una tavolozza di colori simile a quella trovata in
altri software ( vedi la Figura 3-4 ) . Seleziona un colore, ed usa i valori R, G e B come parametri
per le tue funzioni di background( ), fill( ), o stroke( ).

Esempio 3-17: Impostare la Trasparenza


Con l'aggiunta di un quarto parametro opzionale a fill( ) o stroke( ) , Puoi controllare la trasparenza.
Questo quarto parametro conosciuto come il valore alpha , ed anch'esso usato in un intervallo
che va da 0 a 255 per impostare il grado di trasparenza. Il valore 0 definisce il colore come
completamente trasparente ( non viene visualizzato) , il valore 255 completamente opaco, e i
valori che si trovano tra questi estremi provocano la fusione dei colori sullo schermo.

size(480, 120);
noStroke();
smooth();
background(204, 226, 225); // Colore blu chiaro
fill(255, 0, 0, 160); // Colore rosso
ellipse(132, 82, 200, 200); // Cerchio rosso
fill(0, 255, 0, 160); // Colore verde
ellipse(228, -16, 200, 200); // Cerchio verde
fill(0, 0, 255, 160); // Colore blu
ellipse(268, 118, 200, 200); // Cerchio blu

Forme Personalizzate
Non sei limitato ad usare queste forme geometriche di base puoi anche definire nuove forme
connettendo delle serie di punti .

Esempio 3-18: Disegnare una Freccia


La funzione beginShape( ) dichiara il punto di partenza di una nuova forma. La funzione vertex( )
usata per definire ogni coppia di coordinate X e Y per la forma . Infine, endShape( ) usata per
segnalare la fine della forma.

size(480, 120);
beginShape();
vertex(180, 82);
vertex(207, 36);
vertex(214, 63);
vertex(407, 11);
vertex(412, 30);
vertex(219, 82);
vertex(226, 109);
endShape();

Esempio 3-19: Chiudere l'Apertura


Quando esegui l'esempio 3-18, vedrai che il primo e l'ultimo punto non sono connessi. Per farlo,
aggiungiamo la parola CLOSE come un parametro in endShape( ), in questo modo:

size(480, 120);
beginShape();
vertex(180, 82);
vertex(207, 36);
vertex(214, 63);
vertex(407, 11);
vertex(412, 30);
vertex(219, 82);
vertex(226, 109);
endShape(CLOSE);

Esempio 3-20: Creare alcune Creature


La capacit di definire forme con la funzione vertex( ) l'abilit di creare forme con contorni
complessi. Processing pu disegnare migliaia e migliaia di linee in una volta per riempire lo
schermo con forme fantastiche che fuoriescono dalla tua immaginazione . Un esempio modesto ma
pi complesso quello che segue:

size(480, 120);
smooth();
// Left creature
beginShape();
vertex(50, 120);
vertex(100, 90);
vertex(110, 60);
vertex(80, 20);
vertex(210, 60);
vertex(160, 80);
vertex(200, 90);
vertex(140, 100);
vertex(130, 120);
endShape();
fill(0);
ellipse(155, 60, 8, 8);
// Right creature
fill(255);
beginShape();
vertex(370, 120);
vertex(360, 90);
vertex(290, 80);
vertex(340, 70);
vertex(280, 50);
vertex(420, 10);
vertex(390, 50);
vertex(410, 90);
vertex(460, 120);
endShape();
fill(0);
ellipse(345, 50, 10, 10);

Commenti
Gli esempi in questo capitolo usano un doppio slash ( // ) alla fine di una riga per aggiungere dei
commenti al codice. I commenti sono parti del programma che vengono ignorati quando questo
viene eseguito. Sono utili per creare note per te stesso che spiegano cosa sta succedendo all'interno
del codice . Se altri stanno leggendo il tuo codice, i commenti sono particolarmente importanti per
aiutarli a capire il tuo processo di pensiero.

I commenti sono particolarmente utili inoltre per un numero di opzioni differenti, come quando si
prova a scegliere il colore giusto. Ad esempio, posso provare a trovare il rosso giusto per un'ellissi.

size(200, 200);
fill(165, 57, 57);
ellipse(100, 100, 80, 80);

Ora supponiamo di voler provare un rosso differente, ma non vogliamo perdere quello vecchio.
Posso copiare e incollare la linea, fare un cambiamento, poi commentare quella vecchia.

size(200, 200);
//fill(165, 57, 57);
fill(144, 39, 39);
ellipse(100, 100, 80, 80);

Collocare // all'inizio di una linea la disabilita temporaneamente. Oppure posso rimuovere le // e


collocarle davanti ad un'altra linea se voglio provarla ancora:

size(200, 200);
fill(165, 57, 57);
//fill(144, 39, 39);
ellipse(100, 100, 80, 80);

NOTA: Come scorciatoia, puoi anche usare Ctrl-/ (Cmd-/ per il Mac) per aggiungere o rimuovere i
commenti dalla linea corrente o da un blocco di testo selezionato. Puoi anche commentare pi linee
in una volta con la notazione di commento alternativa introdotta nell'Appendice A.

Lavorando con gli schizzi di Processing, ti troverai a creare dozzine di ripetizioni di idee: usare i
commenti per creare annotazioni o per disabilitare il codice pu aiutarti a tenere traccia di opzioni
differenti.
Robot 1: Disegna
Questo P5, il robot di Processing. Ci sono 8 diversi programmi per disegnarlo e animarlo in
questo libro ognuno esplora un'idea differente di programmazione. Il design di P5 ispirato da
Sputnik 1 (1957), Shakey dallo Stanford Research Institute (1966-1972), il drone combattente in
Dune di David Lynch (1984), e HAL 9000 da 2001:Odissea nello Spazio (1968), oltre ad altri robot
che ammiriamo.

Il primo programma del robot usa la funzione di disegno introdotta nel capitolo precedente. I
parametri delle funzioni fill( ) e stroke( ) regolano i valori di grigio. Le funzioni line( ), ellipse( ), e
rect( ) definiscono le forme che creano il collo,le antenne, il corpo e la testa del robot. Per prendere
maggiore confidenza con le funzioni, esegui il programma e cambia i valori per riprogettare il
robot:

size(720, 480);
smooth();
strokeWeight(2);
background(204);
ellipseMode(RADIUS);
// Collo
stroke(102); // Imposta il contorno in grigio
line(266, 257, 266, 162); // Sinistra
line(276, 257, 276, 162); // Centro
line(286, 257, 286, 162); // Destra
// Antenne
line(276, 155, 246, 112); // Bassa
line(276, 155, 306, 56); // Alta
line(276, 155, 342, 170); // Media
// Corpo
noStroke(); // Disabilita il contorno
fill(102); // Imposta il riempimento in grigio
ellipse(264, 377, 33, 33); // Sfera antigravit
fill(0); // Imposta il riempimento in nero
rect(219, 257, 90, 120); // Corpo principale
fill(102); // Imposta il riempimento in grigio
rect(219, 274, 90, 6); // Banda grigia
// Testa
fill(0); // Imposta il riempimento in nero
ellipse(276, 155, 45, 45); // Testa
fill(255); // Imposta il riempimento in bianco
ellipse(288, 150, 14, 14); // Occhio grande
fill(0); // Imposta il riempimento in nero
ellipse(288, 150, 3, 3); // Pupilla
fill(153); // Imposta il riempimento in grigio chiaro
ellipse(263, 148, 5, 5); // Occhio piccolo 1
ellipse(296, 130, 4, 4); // Occhio piccolo 2
ellipse(305, 162, 3, 3); // Occhio piccolo 3
4/Variabili

Una variabile immagazzina un valore nella memoria cos da poter


essere usata pi tardi nel programma. La variabile pu essere usata
diverse volte all'interno di un singolo programma, ed il valore
viene cambiato facilmente mentre il programma in esecuzione.
La ragione primaria per cui usiamo le variabili per evitare di ripeterci all'interno del codice. Se
stai digitando lo stesso numero pi di una volta, prendi in considerazione di trasformarlo in una
variabile per rendere il tuo codice pi universale e facile da aggiornare.

Esempio 4-1: Riutilizzare gli Stessi Valori


Come dimostrazione, quando trasformi in variabili la coordinata X e il diametro per i tre cerchi in
questo esempio, gli stessi valori sono usati per ogni ellisse:

size(480, 120);
smooth();
int y = 60;
int d = 80;
ellipse(75, y, d, d); // Sinistra
ellipse(175, y, d, d); // Centro
ellipse(275, y, d, d); // Destra

Esempio 4-2: Cambia i valori


Perci semplicemente cambiando le variabili y e d vengono alterate tutte e tre le ellissi:

size(480, 120);
smooth();
int y = 100;
int d = 130;
ellipse(75, y, d, d); // Sinistra
ellipse(175, y, d, d); // Centro
ellipse(275, y, d, d); // Destra

Senza le variabili, avresti bisogno di cambiare la coordinata y usata nel codice tre volte, e il
diametro sei volte. Quando si confrontano gli Esempi 4-1 e 4-2, notiamo come le tre righe in fondo
siano le stesse, e solamente le due righe con le variabili al centro sono differenti. Le variabili ti
permettono di separare righe di codice che richiedono cambiamenti da quelle che non lo richiedono,
per creare programmi pi facili da modificare. Ad esempio, se poniamo delle variabili che
controllano i colori e la dimensione delle forme in un unico luogo, poi potrai velocemente esplorare
differenti opzioni visive concentrandoti solo su poche righe di codice.

Creare Variabili
Quando crei le tue variabili, determini il nome (name), il tipo di dati (data type), ed il valore
(value). Il nome come decidi di chiamare la variabile. Scegli un nome che sia descrittivo di ci
che contenuto nella variabile, ma allo stesso tempo cerca di essere coerente e non troppo prolisso.
Ad esempio, la variabile chiamata radius sar pi chiara di r quando in seguito leggerai il
codice.

La gamma di valori che pu essere immagazzinata nella variabile definita dal suo data type. Per
esempio, il tipo integer (intero) pu memorizzare numeri senza decimali (numeri interi). Nel
codice , integer abbreviato con int . Ci sono data type per depositare ogni genere di dati: interi,
numeri in virgola mobile (decimali), caratteri, parole, immagini, font, e cos via.

Le variabili devono essere innanzitutto dichiarate, per mettere da parte uno spazio nella memoria
del computer per memorizzare le informazioni. Quando si dichiara una variabile, puoi anche aver
bisogno di specificare il tipo di dati (come int), il quale indica quale genere di informazione stata
memorizzata. Dopo che il tipo di dati e il nome sono stati definiti, pu essere assegnato un valore
alla variabile:

int x; // Dichiara x come una variabile intera


x = 12; // Assegna un valore alla x

Questo codice fa la stessa cosa, ma pi breve:

int x = 12; // Dichiara x come una variabile intera e assegna un


valore

Il nome della tipologia di dati incluso nella riga di codice che dichiara una variabile, ma non viene
scritto un'altra volta. Ogni volta che il data type viene scritto davanti al nome di una variabile, il
computer pensa che tu stia provando a dichiarare un'altra variabile. Non puoi avere due variabili
con lo stesso nome nella stessa parte di programma ( vedi l'Appendice D ), perch il programma
avr un errore:

int x; // dichiara x come una variabile int


int x = 12; // ERRORE! Non puoi avere qui due variabili con lo
stesso nome

Variabili di Processing

Processing possiede una serie di variabili speciali per depositare informazioni riguardo al
programma mentre esso in esecuzione. Ad esempio, la larghezza e l'altezza della finestra sono
memorizzate in variabili chiamate width ed height. Questi valori sono impostati nella funzione
size( ). Possono essere usati per disegnare elementi relativi alla dimensione della finestra, anche se
la riga di size( ) viene cambiata.

Esempio 4-3: Regola la Dimensione, Vedi Cosa Accade


In questo esempio, cambia i parametri della funzione size( ) per vedere come funziona:
size(480, 120);
smooth();
line(0, 0, width, height); // Linea da (0,0) a (480, 120)
line(width, 0, 0, height); // Linea da (480, 0) a (0, 120)
ellipse(width/2, height/2, 60, 60);

Altre variabili speciali tengono traccia dello status del mouse, dei valori della tastiera, ed altro
ancora. Di questi si parler nel Capitolo 5.

Un po' di Matematica

Le persone spesso ritengono che la matematica e la programmazione sono la stessa cosa. Sebbene
la conoscenza della matematica pu essere utile per certe tipologie di codificazione, l'aritmetica di
base ricopre le parti pi importanti.

Esempio 4-4: Aritmetica di Base


size(480, 120);
int x = 25;
int h = 20;
int y = 25;
rect(x, y, 300, h); // Superiore
x = x + 100;
rect(x, y + h, 300, h); // Centrale
x = x - 250;
rect(x, y + h*2, 300, h); // Inferiore

Nel codice, simboli come +, -, e * sono chiamati operatori. Quando sono posizionati tra due valori,
creano un' espressione. Ad esempio, 5+9 e 1024-512 sono entrambe espressioni. Gli operatori per le
operazioni base di matematica sono:

+ Addizione
- Sottrazione
* Moltiplicazione
/ Divisione
= Assegnazione

Processing ha una serie di regole per definire quale operatore ha la precedenza sugli altri, ci
significa che decide quale calcolo viene risolto per primo, secondo, terzo, e cos via. Queste regole
definiscono l'ordine in cui il codice viene eseguito. Una piccola cognizione riguardo questo
argomento inizia una lunga strada verso la comprensione di come una piccola riga di codice come
questa pu funzionare:

int x = 4 + 4 * 5; // Assegna 24 ad x

L'espressione 4*5 valutata per prima poich la moltiplicazione ha la priorit pi alta. Come
seconda cosa, 4 addizionato al prodotto di 4*5 per ottenere 24. Infine, siccome l'operatore di
assegnazione ( il simbolo uguale ) ha la precedenza pi bassa, il valore 24 assegnato alla variabile
x. Ci chiarito con le parentesi, ma il risultato lo stesso:

int x = 4 + (4 * 5); // Assegna 24 ad x

Se vuoi costringere l'addizione ad essere verificata per primo, basta solamente muovere le parentesi.
Poich ci che tra parentesi ha una precedenza pi alta della moltiplicazione, l'ordine viene
cambiato ed il calcolo viene influenzato:

int x = (4 + 4) * 5; // Assegna 40 ad x

Un acronimo per quest'ordine spesso insegnato nelle classi di matematica: PEMDAS, che sta per
Parentesi, Esponenti, Moltiplicazione, Divisione, Addizione, Sottrazione, dove le parentesi hanno la
pi alta priorit e la sottrazione la pi bassa. L'ordine completo delle operazioni si trova
nell'Appendice C.

Alcuni calcoli vengono usati cos frequentemente nella programmazione che si sono sviluppate
delle abbreviazioni; sempre una buona cosa salvare alcune parole chiave. Ad esempio, puoi fare
un'addizione ad una variabile, oppure una sottrazione, con un unico operatore:

x += 10; // come dire x = x + 10


y -= 15; // come dire y = y 15

E' inoltre cosa comune addizionare o sottrarre 1 da una variabile, cos esiste anche un'abbreviazione
per questo caso. Gli operatori ++ e - - fanno proprio questo:

x++; // come dire x = x + 1


y--; // come dire y = y 1

Altre abbreviazioni possono essere trovate nelle referenze.

Ripetizione
Nel momento in cui scriverai altri programmi, noterai che ricorreranno dei pattern quando le righe
di codice verranno ripetute, ma con sottili variazioni. Una struttura del codice chiamata ciclo for
rende possibile l'esecuzione di una riga di codice pi di una volta per condensare questo tipo di
ripetizione in poche righe. Questo rende i tuoi programmi modulari e pi facili da modificare.

Esempio 4-5: Fare la stessa cosa pi e pi volte


Questo esempio possiede il tipo di pattern che pu essere semplificato con un ciclo for:

size(480, 120);
smooth();
strokeWeight(8);
line(20, 40, 80, 80);
line(80, 40, 140, 80);
line(140, 40, 200, 80);
line(200, 40, 260, 80);
line(260, 40, 320, 80);
line(320, 40, 380, 80);
line(380, 40, 440, 80);

Esempio 4-6; Usa un ciclo for


La stessa cosa pu essere fatta con un ciclo for, e con meno codice:

size(480, 120);
smooth();
strokeWeight(8);
for (int i = 20; i < 400; i += 60) {
line(i, 40, i + 60, 80);
}

Il ciclo for differisce in molti modi dal codice che abbiamo scritto fino ad ora. Nota le parentesi
graffe, i caratteri { e } . Il codice all'interno delle parentesi graffe chiamato blocco. questo il
codice che viene ripetuto in ogni iterazione del ciclo for .
All'interno delle parentesi ci sono tre dichiarazioni, separate da punti e virgola, che lavorano
assieme per controllare quante volte il codice all'interno del blocco viene eseguito. Da sinistra a
destra, queste dichiarazioni si riferiscono come l'inizializzazione (init) , il test, e l'aggiornamento
(update) .

for (init; test; update) {


dichiarazioni
}

La init tipicamente dichiara una nuova variabile da usare all'interno del ciclo for e ne assegna un
valore. Il nome della variabile i usato di frequente, ma in realt non c' nulla di speciale riguardo
questo nome. Il test sonda il valore di questa variabile, e l' update cambia il valore della variabile.
La Figura 4-1 mostra l'ordine in cui vengono eseguiti e come controllino le dichiarazioni di codice
all'interno del blocco.

Il test ha bisogno di ulteriori spiegazioni. sempre un' espressione relazionale che compara due
valori con un operatore relazionale. In questo esempio, l'espressione i < 400 e l'operatore il
simbolo < ( minore di). Gli operatori relazionali pi comuni sono:

> Maggiore di
< Minore di
>= Maggiore o uguale a
<= Minore o uguale a
== Uguale a
!= Non uguale a

L'espressione relazionale valuta sempre il vero o il falso. Ad esempio, l'espressione 5>3 vera.
Possiamo porre la domanda, cinque maggiore di tre? siccome la riposta si, diciamo che
l'espressione vera.
Per l'espressione 5<3, chiediamo, cinque minore di tre?. Siccome la risposta no, diciamo
che l'espressione falsa. Quando la valutazione vera, il codice all'interno del blocco viene
eseguito, e quando falso, il codice all'interno del blocco non viene eseguito ed il ciclo for si ferma.

Esempio 4-7: Contrarre i Muscoli del Ciclo For


La forza fondamentale quando si lavora con un ciclo for l'abilit di fare rapidi cambiamenti al
codice. Poich il codice all'interno del blocco solitamente eseguito molteplici volte, un
cambiamento al blocco amplificato quando il codice in esecuzione. Modificando anche
lievemente l'Esempio 4-6, possiamo creare una serie di pattern differenti:

size(480, 120);
smooth();
strokeWeight(2);
for (int i = 20; i < 400; i += 8) {
line(i, 40, i + 60, 80);
}

Esempio 4-8: Aprire le Linee a Ventaglio

size(480, 120);
smooth();
strokeWeight(2);
for (int i = 20; i < 400; i += 20) {
line(i, 0, i + i/2, 80);
}

Esempio 4-9: Attorcigliare le Linee

size(480, 120);
smooth();
strokeWeight(2);
for (int i = 20; i < 400; i += 20) {
line(i, 0, i + i/2, 80);
line(i + i/2, 80, i*1.2, 120);
}

Esempio 4-10: Incorporare un Ciclo For dentro un altro


Quando un ciclo for annidato in un altro, il numero delle ripetizioni viene moltiplicato. Per prima
cosa, diamo un'occhiata a questo breve esempio, poi lo scomporremo nell'Esempio 4-11:

size(480, 120);
background(0);
smooth();
noStroke();
for (int y = 0; y <= height; y += 40) {
for (int x = 0; x <= width; x += 40) {
fill(255, 140);
ellipse(x, y, 40, 40);
}
}

Esempio 4-11: Righe e Colonne


In questo esempio, i cicli for sono adiacenti, invece di essere annidati l'uno dentro l'altro. Il risultato
mostra che un ciclo for disegna una colonna di 4 cerchi e l'altro una riga di 13 cerchi:

size(480, 120);
background(0);
smooth();
noStroke();
for (int y = 0; y < height+45; y += 40) {
fill(255, 140);
ellipse(0, y, 40, 40);
}
for (int x = 0; x < width+45; x += 40) {
fill(255, 140);
ellipse(x, 0, 40, 40);
}

Quando uno di questi cicli for posizionato dentro l'altro, come nell'esempio 4-10, le 4 ripetizioni
del primo ciclo sono aggiunte alle 13 del secondo allo scopo di eseguire il codice all'interno del
blocco incorporato per 52 volte ( 4*13=52).

L'Esempio 4-10 un'ottima base per esplorare diversi tipi di pattern visivi ripetitivi. L'esempio che
segue mostra un paio di modi che possono essere estesi, ma questo solo un minuscolo esempio di
quello che possibile fare. Nell'Esempio 4-12, il codice disegna una linea da ciascun punto della
griglia fino al centro dello schermo. Nell'Esempio 4-13, le ellissi si riducono ad ogni nuova riga e si
spostano verso destra addizionando la coordinata y alla coordinata x .

Esempio 4-12: Spilli e Linee

size(480, 120);
background(0);
smooth();
fill(255);
stroke(102);
for (int y = 20; y <= height-20; y += 10) {
for (int x = 20; x <= width-20; x += 10) {
ellipse(x, y, 4, 4);
// Disegna una linea al centro della visualizzazione
line(x, y, 240, 60);
}
}

Esempio 4-13: Punti in Mezzotono

size(480, 120);
background(0);
smooth();
for (int y = 32; y <= height; y += 8) {
for (int x = 12; x <= width; x += 15) {
ellipse(x + y, y, 16 - y/10.0, 16 - y/10.0);
}
}

Robot 2: Variabili
Le variabili introdotte in questo programma rendono l'aspetto del codice pi complesso del Robot 1
(vedi Robot 1: Disegna nel Capitolo 3), ma ora molto pi facile da modificare, poich i numeri
che dipendono gli uni dagli altri sono sistemati in un unico luogo. Ad esempio, il collo pu essere
disegnato basandosi sulla variabile bodyHeight . Il gruppo di variabili in cima al codice controlla gli
aspetti del robot che vogliamo cambiare: posizione, altezza del corpo e altezza del collo. Puoi
osservare alcune delle serie di variazioni possibili nella figura; da sinistra a destra, ecco i valori che
ne corrispondono:
y = 390
bodyHeight = 180
neckHeight = 40

y = 460
bodyHeight = 260
neckHeight = 95

y = 310
bodyHeight = 80
neckHeight = 10

y = 420
bodyHeight = 110
neckHeight = 140

Quando modifichi il tuo codice per usare variabili invece di numeri, pianifica i cambiamenti
attentamente, e opera le modifiche a piccoli passi. Ad esempio, quando il programma viene scritto,
viene creata una variabile alla volta per minimizzare la complessit della transizione. Dopo che una
variabile stata aggiunta ed il codice stato eseguito per assicurare che funzioni, viene aggiunta la
prossima variabile:

int x = 60; // coordinata-x


int y = 420; // coordinata-y
int bodyHeight = 110; // Altezza Corpo
int neckHeight = 140; // Altezza Collo
int radius = 45; // Raggio Testa
int ny = y - bodyHeight - neckHeight - radius; // Neck Y
size(170, 480);
smooth();
strokeWeight(2);
background(204);
ellipseMode(RADIUS);
// Collo
stroke(102);
line(x+2, y-bodyHeight, x+2, ny);
line(x+12, y-bodyHeight, x+12, ny);
line(x+22, y-bodyHeight, x+22, ny);
// Antenne
line(x+12, ny, x-18, ny-43);
line(x+12, ny, x+42, ny-99);
line(x+12, ny, x+78, ny+15);
// Corpo
noStroke();
fill(102);
ellipse(x, y-33, 33, 33);
fill(0);
rect(x-45, y-bodyHeight, 90, bodyHeight-33);
fill(102);
rect(x-45, y-bodyHeight+17, 90, 6);
// Testa
fill(0);
ellipse(x+12, ny, radius, radius);
fill(255);
ellipse(x+24, ny-6, 14, 14);
fill(0);
ellipse(x+24, ny-6, 3, 3);
fill(153);
ellipse(x, ny-8, 5, 5);
ellipse(x+30, ny-26, 4, 4);
ellipse(x+41, ny+6, 3, 3);
5/Risposta
Un tipo di codice che risponda agli input del mouse, della tastiera,
e ad altri dispositivi ha bisogno di essere eseguito in
continuazione. Per far si che questo accada, inserisci le righe che
devono essere aggiornate in una funzione di Processing chiamata
draw( ).
Esempio 5-1: La funzione draw( ).

Per vedere come lavora la funzione draw( ), esegui questo esempio:

void draw() {
// Visualizza il conteggio dei frame sulla console
println("Sto disegnando");
println(frameCount);
}

Vedrai ci che segue:

Sto disegnando
1
Sto disegnando
2
Sto disegnando
3

Il codice contenuto all'interno del blocco draw( ) scorre dalla cima al fondo, poi si ripete finch non
esci dal programma cliccando sul pulsante Stop o chiudendo la finestra. Ogni ciclo all'interno del
draw( ) chiamato frame. (la frequenza di default di 60 frame al secondo, ma pu essere
cambiata. Vedi l'Esempio 7-2 per maggiori informazioni.) Nel programma dell'esempio precedente,
la funzione println( ) scrive il testo Sto disegnando seguito dal conteggio del frame corrente
calcolato dalla variabile speciale frameCount (1,2,3,...). Il testo appare sulla console, l'area nera
nella finestra di editor di Processing.

Esempio 5-2: La Funzione Setup( )


Per completare la funzione ricorrente draw( ), Processing inserisce una funzione chiamata setup( )
che viene eseguita solo una volta quando il programma parte:
void setup() {
println("Sto iniziando");
}
void draw() {
println("Sono in esecuzione");
}

Quando il codice in esecuzione, ci che segue viene trascritto sulla console:

Sto iniziando
Sono in esecuzione
Sono in esecuzione
Sono in esecuzione

Il testo Sono in esecuzione continua ad essere scritto nella console finch il programma non viene
fermato.

In un programma tipico, il codice all'interno di setup( ) usato per determinare i valori di partenza.
La prima riga sempre la funzione size( ), spesso seguita dal codice che imposta i colori di partenza
per il riempimento ed il contorno, o magari per caricare immagini e font. (Se non inserisci la
funzione size( ) , la finestra di visualizzazione sar di 100x100 pixel.)

Ora sai come usare setup( ) e draw( ) , ma non finisce qua. C' un altro luogo per inserire il codice,
puoi anche inserire delle variabili all'esterno di setup( ) e draw( ) . Se crei una variabile all'interno di
setup( ) , non puoi usarla all'interno di draw( ) , quindi hai bisogno di posizionare queste variabili da
qualche altra parte. Queste variabili sono chiamate variabili globali, perch possono essere usate
ovunque (globalmente) all'interno del programma. Questo diventa chiaro quando elenchiamo
l'ordine in cui il codice viene eseguito:

1. Sono create le variabili dichiarate fuori setup( ) e draw( ).


2. Il codice all'interno di setup( ) viene eseguito una sola volta.
3. Il codice all'interno di draw( ) eseguito continuamente.

Esempio 5-3: setup( ) incontra draw( )


L'esempio che segue raccoglie tutto insieme:

int x = 280;
int y = -100;
int diameter = 380;
void setup() {
size(480, 120);
smooth();
fill(102);
}
void draw() {
background(204);
ellipse(x, y, diameter, diameter);
}
Seguire
Ora che abbiamo codice che viene eseguito continuativamente, possiamo prender traccia della
posizione del mouse e usare questi numeri per muovere gli elementi sullo schermo.

Esempio 5-4: Tracciare il Mouse


La variabile mouseX memorizza la coordinata-x, e la variabile mouseY immagazzina la coordinata-
y:

void setup() {
size(480, 120);
fill(0, 102);
smooth();
noStroke();
}
void draw() {
ellipse(mouseX, mouseY, 9, 9);
}

In questo esempio, ogni volta che il codice all'interno del blocco draw( ) viene eseguito, un nuovo
cerchio disegnato sulla finestra. Questa immagine stata fatta muovendo il mouse qua e l
controllando la posizione del cerchio. Poich il riempimento impostato per essere parzialmente
trasparente, le aree di nero pi denso mostrano dove il mouse ha passato pi tempo e dove si
mosso pi lentamente. I cerchi che sono pi spaziati tra loro mostrano dove il mouse si mosso pi
velocemente.

Esempio 5-5: Il Punto ti Segue


In questo esempio, un nuovo cerchio aggiunto alla finestra ogni volta che il codice all'interno di
draw( ) eseguito. Per rinnovare lo schermo e visualizzare solo in nuovo cerchio, inserisci la
funzione background( ) all'inizio di draw( ) prima che la forma sia disegnata:

void setup() {
size(480, 120);
fill(0, 102);
smooth();
noStroke();
}
void draw() {
background(204);
ellipse(mouseX, mouseY, 9, 9);
}

La funzione background( ) ripulisce l'intera finestra, quindi sii sicuro di inserirla sempre prima delle
altre funzioni all'interno di draw( ) ; in caso contrario, le forme disegnate prima saranno cancellate.

Esempio 5-6: Disegna in Modo Continuo


Le variabili pmouseX e pmouseY assumono la posizione del mouse al frame precedente.
Come mouseX e mouseY , queste variabili speciali sono aggiornate ogni volta che draw( ) viene
eseguito. Quando sono combinate, possono essere usate per disegnare linee continue connettendo la
posizione corrente con quella pi recente.
void setup() {
size(480, 120);
strokeWeight(4);
smooth();
stroke(0, 102);
}
void draw() {
line(mouseX, mouseY, pmouseX, pmouseY);
}

Esempio 5-7: Imposta lo Spessore al Volo


Le variabili pmouseX e pmouseY possono essere usate anche per calcolare la velocit del mouse.
Questo viene ottenuto dalla misurazione della distanza tra la posizione del mouse corrente e quella
pi recente. Se il mouse si muove lentamente, la distanza piccola, ma se il mouse inizia a
muoversi pi velocemente, la distanza cresce. Una funzione chiamata dist( ) semplifica il calcolo,
come mostrato nell'esempio seguente. In questo caso, la velocit del mouse usata per regolare lo
spessore della linea disegnata:

void setup() {
size(480, 120);
smooth();
stroke(0, 102);
}
void draw() {
float weight = dist(mouseX, mouseY, pmouseX, pmouseY);
strokeWeight(weight);
line(mouseX, mouseY, pmouseX, pmouseY);
}

Esempio 5-8: l'Easing lo fa


Nell'esempio 5-7, i valori dal mouse sono convertiti direttamente in posizioni sullo schermo. Ma a
volte puoi volere che i valori seguano il mouse vagamente, rimanendo indietro per creare un
movimento pi fluido. Questa tecnica chiamata Easing. Con l'easing abbiamo due valori: il valore
corrente ed il valore in cui ci andremo a muovere ( vedi figura 5-1). Ad ogni passo nel programma,
il valore corrente si sposta leggermente pi vicino al valore che abbiamo come obiettivo:

float x;
float easing = 0.01;
float diameter = 12;
void setup() {
size(220, 120);
smooth();
}
void draw() {
float targetX = mouseX;
x += (targetX - x) * easing;
ellipse(x, 40, 12, 12);
println(targetX + " : " + x);
}

Il valore della variabile x sempre pi vicino a targetX. La velocit in cui raggiunger targetX
impostata con la variabile easing, un numero tra 0 e 1. Un piccolo valore per l'easing causa un
ritardo maggiore che un valore pi grande. Con un valore di easing impostato ad 1, non abbiamo
ritardo. Quando esegui l'Esempio 5-8, il valori attuali sono mostrati nella Console attraverso la
funzione println( ) . Quando muoviamo il mouse, nota come i numeri sono distanti, ma quando il
mouse smette di muoversi,il valore della x si avvicina a targetX.

Tutto il lavoro in questo esempio avviene nella riga che inizia con x +=.
Qui viene calcolata la differenza tra l'obiettivo ed il valore corrente, poi moltiplicata dalla variabile
di easing e aggiunta alla x per portarla vicino all'obiettivo.

Esempio 5-9:Smussa le Linee con l'Easing


In questa dimostrazione, la tecnica easing applicata all'Esempio 5-7. Confrontandoli, le linee sono
pi smussate:

float x;
float y;
float px;
float py;
float easing = 0.05;
void setup() {
size(480, 120);
smooth();
stroke(0, 102);
}
void draw() {
float targetX = mouseX;
x += (targetX - x) * easing;
float targetY = mouseY;
y += (targetY - y) * easing;
float weight = dist(x, y, px, py);
strokeWeight(weight);
line(x, y, px, py);
py = y;
px = x;
}

Mappare
Quando vengono usati dei numeri per disegnare sullo schermo, spesso utile convertirne i valori da
una serie di numeri ad un'altra.

Esempio 5-10: Riportare i Valori ad una Serie


Il valore della variabile mouseX usualmente si trova tra lo 0 e la larghezza della finestra, ma
potresti desiderare di rimappare questi valori ad una gamma differente di coordinate. Puoi farlo
facendo dei calcoli, come dividere mouseX per un numero al fine di ridurre l'intervallo numerico e
poi addizionare o sottrarre un numero per spostarlo a destra o a sinistra:

void setup() {
size(240, 120);
strokeWeight(12);
smooth();
}
void draw() {
background(204);
stroke(255);
line(120, 60, mouseX, mouseY); // Linea bianca
stroke(0);
float mx = mouseX/2 + 60;
line(120, 60, mx, mouseY); // Linea nera
}

La funzione map( ) un modo pi generico di operare questo tipo di cambiamento. Converte una
variabile da una serie di numeri ad un'altra. Il primo parametro la variabile che dev'essere
convertita, il secondo ed il terzo parametro sono il valore pi basso ed il valore pi alto di questa
variabile, ed il quarto ed il quinto parametro sono rispettivamente i valori pi alto e pi basso
desiderati.
La funzione map( ) ti permette di tralasciare la matematica che c' dietro la conversione.

Esempio 5-11: Mappare con la Funzione map( )


Questo esempio riconsidera l'Esempio 5-10 usando map( ):

void setup() {
size(240, 120);
strokeWeight(12);
smooth();
}
void draw() {
background(204);
stroke(255);
line(120, 60, mouseX, mouseY); // Linea bianca
stroke(0);
float mx = map(mouseX, 0, width, 60, 180);
line(120, 60, mx, mouseY); // Linea nera
}

La funzione map( ) rende il codice pi facile da leggere, poich i valori minimo e massimo sono
chiaramente scritti come parametri. In questo esempio,i valori di mouseX tra lo 0 e width sono
convertiti ad un numero che va da 60 (quando mouseX 0) fino a 180 (quando mouseX ha il valore
di width) Troverai l'utile funzione map( ) in molti esempi all'interno di questo libro.

Click
In aggiunta alla posizione del mouse, Processing pu anche prender nota di quando il pulsante del
mouse premuto. La variabile mousePressed ha un valore differente quando il pulsante premuto e
quando non lo . La variabile mousePressed ha una tipologia di dati chiamato booleana, cio che ha
solamente due possibili valori: vero e falso. Il valore di mousePressed vero quando il mouse
premuto.

Esempio 5-12: Cliccare il Mouse


La variabile mousePressed usata insieme alla dichiarazione if per determinare quando una riga di
codice dev'essere eseguita e quando non dev'esserlo. Prova questo esempio prima di andare avanti
ulteriormente:

void setup() {
size(240, 120);
smooth();
strokeWeight(30);
}
void draw() {
background(204);
stroke(102);
line(40, 0, 70, height);
if (mousePressed == true) {
stroke(0);
}
line(0, 70, width, 50);
}

In questo programma, il codice all'interno del blocco if viene eseguito solo quando un pulsante del
mouse viene premuto. Quando un pulsante non premuto, questo codice viene ignorato. Come il
ciclo for trattato in Ripetizione nel Capitolo 4, anche l'if ha un test che valuta con la meccanica
del true o false.

If (test) {
dichiarazioni
}

Quando il test vero, il codice all'interno del blocco viene eseguito; quando il test falso , il codice
non viene eseguito. Il computer determina se il test vero o falso valutando l'espressione all'interno
delle parentesi. (se hai bisogno di rinfrescare la memoria, la discussione riguardante le espressioni
relative nell'esempio 4-6.)

Il simbolo == confronta i valori sulla sinistra e sulla destra per valutare se sono equivalenti. Il
simbolo == diverso dall'operatore di assegnazione, il singolo simbolo =. Il simbolo ==
chiede,Queste due cose sono uguali? invece il simbolo = imposta il valore di una variabile.

NOTA: un errore comune, anche per programmatori esperti, scrivere nel codice = quando invece
volevi scrivere ==. Il software di Processing non ti avvertir sempre quando questo accade, quindi
cerca di essere preciso.

In alternativa, il testo all'interno di draw nell'Esempio 5-12 pu venir scritto in questo modo:

if (mousePressed) {

Le variabili booleane, inclusa mousePressed, non hanno bisogno del confronto esplicito con
l'operatore ==, perch pu esser solo vero o falso.

Esempio 5-13: Individuare Quando non Cliccato


Un blocco if singolo ti da la possibilit di scegliere tra l'eseguire una parte di codice o trascurarla.
Puoi estendere un blocco if con un blocco else, permettendo al tuo programma di scegliere tra due
opzioni. Il codice all'interno del blocco else viene eseguito quando il valore del test del blocco if
falso. Ad esempio, il colore del contorno per un programma pu essere bianco quando il mouse non
premuto, e pu cambiare nel colore nero quando il pulsante premuto:

void setup() {
size(240, 120);
smooth();
strokeWeight(30);
}
void draw() {
background(204);
stroke(102);
line(40, 0, 70, height);
if (mousePressed) {
stroke(0);
} else {
stroke(255);
}
line(0, 70, width, 50);
}

Esempio 5-14: Pulsanti del Mouse Multipli


Processing inoltre registra quale pulsante premuto se ne hai pi di uno sul mouse.
La variabile mouseButton pu avere uno di questi tre valori: LEFT, CENTER, o RIGHT.
Per provare quale pulsante stato premuto, c' bisogno dell'operatore == , come mostrato qui:

void setup() {
size(120, 120);
smooth();
strokeWeight(30);
}
void draw() {
background(204);
stroke(102);
line(40, 0, 70, height);
if (mousePressed) {
if (mouseButton == LEFT) {
stroke(255);
} else {
stroke(0);
}
line(0, 70, width, 50);
}
}

Un programma pu avere molte pi strutture di if e di else (vedi la Figura 5-2) di quelle trovate in
questi brevi esempi.
Essi possono essere incatenati assieme in lunghe serie, che testino ognuna qualcosa di differente, e i
blocchi di if possono essere incorporati all'interno di altri blocchi di if per creare delle strutture pi
complesse.

Posizione
Una struttura if pu essere usata con i valori di mouseX e mouseY per determinare la posizione del
cursore all'interno della finestra.

Esempio 5-15: Trovare il Cursore


Per esaminare un caso, questo esempio prova a vedere se il cursore sulla parte destra o sulla parte
sinistra di una linea e quindi muove la linea verso il cursore.

float x;
int offset = 10;
void setup() {
size(240, 120);
smooth();
x = width/2;
}
void draw() {
background(204);
if (mouseX > x) {
x += 0.5;
offset = -10;
}
if (mouseX < x) {
x -= 0.5;
offset = 10;
}
line(x, 0, x, height);
line(mouseX, mouseY, mouseX + offset, mouseY - 10);
line(mouseX, mouseY, mouseX + offset, mouseY + 10);
line(mouseX, mouseY, mouseX + offset*3, mouseY);
}

Per scrivere dei programmi che abbiano delle interfacce grafiche per l'utente (pulsanti, caselle, barre
di scorrimento, e cos via), abbiamo bisogno di di scrivere del codice che riconosca quando il
cursore all'interno un'area circoscritta dello schermo.
I due esempi seguenti introducono il modo di controllare se il cursore all'interno di un cerchio e di
un rettangolo. Il codice scritto in maniera modulare con delle variabili, cos che pu essere usato
per verificare qualsiasi cerchio e rettangolo cambiandone i valori.

Esempio 5-16: I Confini di un Cerchio


Per il test sul cerchio, usiamo la funzione dist( ) per prendere la distanza dal centro del cerchio al
cursore, poi proviamo a vedere se questa distanza minore del raggio del cerchio (vedi la
Figura 5-3). Se questo accade, sappiamo che siamo all'interno.
In questo esempio, quando il cursore all'interno dell'area del cerchio, la sua dimensione aumenta:

int x = 120;
int y = 60;
int radius = 12;
void setup() {
size(240, 120);
smooth();
ellipseMode(RADIUS);
}
void draw() {
background(204);
float d = dist(mouseX, mouseY, x, y);
if (d < radius) {
radius++;
fill(0);
} else {
fill(255);
}
ellipse(x, y, radius, radius);
}

Esempio 5-17: I Confini di un Rettangolo


Usiamo un altro approccio per provare se il cursore all'interno di un rettangolo.
Facciamo quattro test separati per capire se il cursore nella parte corretta di ogni margine del
rettangolo, poi compariamo ciascun test e se sono tutti veri, sappiamo che il cursore all'interno del
rettangolo. Ci illustrato nella Figura 5-4. Ogni passo semplice, ma appare complicato quando
tutto ci messo insieme:
int x = 80;
int y = 30;
int w = 80;
int h = 60;
void setup() {
size(240, 120);
}
void draw() {
background(204);
if ((mouseX > x) && (mouseX < x+w) &&
(mouseY > y) && (mouseY < y+h)) {
fill(0);
} else {
fill(255);
}
rect(x, y, w, h);
}

Il test nella dichiarazione if leggermente pi complesso di quello che abbiamo visto.


Quattro test individuali ( esempio, mouseX > x ) sono combinati con l'operatore logico AND, il
simbolo &&, per assicurare che ogni espressione in relazione nella sequenza vera. Se una di esse
falsa, l'intero test diventa falso ed il colore di riempimento non sar impostato sul nero.
Questo spiegato ulteriormente nella voce && delle referenze.

Caratteri tipografici
Processing prende nota di quando un qualsiasi pulsante sulla tastiera viene premuto, cos come
l'ultimo pulsante premuto. Come la variabile mousePressed , la variabile keyPressed vera quando
qualsiasi pulsante viene premuto, e falsa quando non viene premuto alcun pulsante.

Esempio 5-18: Premere un Pulsante

In questo esempio, la seconda linea viene disegnata solamente quando viene premuto un pulsante:

void setup() {
size(240, 120);
smooth();
}
void draw() {
background(204);
line(20, 20, 220, 100);
if (keyPressed) {
line(220, 20, 20, 100);
}
}

La variabile key immagazzina il pulsante che stato premuto pi recentemente. Il data type per la
variabile key char, che un'abbreviazione per character (carattere) , ma di solito viene
pronunciato come la prima sillaba di charcoal. Una variabile char pu contenere qualunque
carattere singolo, il quale include lettere dell'alfabeto, numeri, e simboli.
A differenza del valore string (vedi l'Esempio 6-8), il quale si distingue per le doppie virgolette, il
data type char viene specificato dalle virgolette singole. Questo come una variabile char
dichiarata ed assegnata:

char c = 'A'; // Dichiara ed Assegna 'A' alla variabile c


E questi tentativi causeranno un errore:

char c = "A"; // Errore!Non possibile assegnare una stringa a Char


char h = A; // Errore!Mancano le singole virgolette per 'A'

A differenza della variabile booleana keyPressed , la quale si inverte in false ogniqualvolta un


pulsante rilasciato, la variabile key mantiene il suo valore finch non viene premuto il prossimo
pulsante. L'esempio seguente utilizza il valore di key per disegnare dei caratteri sullo schermo.
Ogni volta che viene premuto un nuovo pulsante, il valore si aggiorna e viene disegnato un nuovo
carattere. Alcuni pulsanti, come Shift ed Alt, non hanno un carattere visibile, cosicch quando li
premerai non sar visualizzato nulla.

Esempio 5-19: Disegnare Alcune Lettere


Questo esempio introduce la funzione textSize( ) per impostare la dimensione delle lettere, la
funzione textAlign( ) per centrare il testo sulla sua coordinata x, e la funzione text( ) per disegnare
lettere. Queste funzioni verranno discusse pi dettagliatamente nelle pagine 84-85.

void setup() {
size(120, 120);
textSize(64);
textAlign(CENTER);
}
void draw() {
background(0);
text(key, 60, 80);
}

Usando la struttura if , possiamo provare a vedere se un pulsante specifico premuto e scegliere di


disegnare qualcosa sullo schermo come risposta.

Esempio 5-20: Verificare i Pulsanti Specifici


In questo esempio, proviamo a digitare una H o una N. Usiamo l'operatore di paragone, il simbolo
= =, per vedere se il valore key uguale ai caratteri che stiamo cercando:

void setup() {
size(120, 120);
smooth();
}
void draw() {
background(204);
if (keyPressed) {
if ((key == 'h') || (key == 'H')) {
line(30, 60, 90, 60);
}
if ((key == 'n') || (key == 'N')) {
line(30, 20, 90, 100);
}
}
line(30, 20, 30, 100);
line(90, 20, 90, 100);
}

Quando stiamo osservando se H o N sono premuti, abbiamo bisogno di verificare sia se sono lettere
maiuscole o minuscole, nel caso che qualcuno prema il pulsante Shift o abbia attivato il Blocco
Maiuscole. Combiniamo insieme i due test con un OR logico, il simbolo ||.
Se traduciamo il primo dichiarato if di questo esempio in linguaggio semplice, questo dice,
Se il pulsante 'h' premuto o il pulsante 'H' premuto. A differenza dell'Esempio 5-17 con l'AND
logico (il simbolo &&), solamente una di queste dev'essere vera perch l'intero test sia vero.

Alcuni pulsanti sono pi difficili da individuare, poich non sono legati d una lettera particolare.
Pulsanti come Shift, Alt, e i tasti freccia sono codificati e richiedono un passo in pi per capire se
sono stati premuti. Prima di tutto abbiamo bisogno di verificare se il pulsante che stato premuto
codificato, poi controlliamo il codice con la variabile keyCode per capire di quale pulsante si tratta.
I valori di keyCode usati pi frequentemente sono ALT, CONTROL, e SHIFT, cos come i pulsanti
freccia, UP, DOWN, LEFT, e RIGHT.

Esempio 5-21: Muoversi con le Frecce Direzionali


L'esempio seguente mostra come verificare se i pulsanti freccia destra o sinistra sono premuti per
muovere un rettangolo:

int x = 215;
void setup() {
size(480, 120);
}
void draw() {
if (keyPressed && (key == CODED)) { // If its a coded key
if (keyCode == LEFT) { // If its the left arrow
x--;
} else if (keyCode == RIGHT) { // If its the right arrow
x++;
}
}
rect(x, 45, 50, 50);
}

Robot 3: Risposta
Questo programma utilizza le variabili introdotte in Robot 2 (vedi Robot 2: Variabili nel capitolo
4) e rende possibile cambiarle mentre il programma in esecuzione cos da far rispondere le forme
al mouse . Il codice all'interno del blocco draw( ) viene eseguito diverse volte al secondo. Ad ogni
nuovo frame, le variabili definite nel programma cambiano in risposta alle variabili mouseX o
mousePressed.

Il valore di mouseX controlla la posizione del Robot con una tecnica di rallentamento cosicch i
movimenti siano meno istantanei e sembrino cos pi naturali. Quando un pulsante del mouse viene
premuto, i valori di neckHeight e bodyHeight cambiano per far abbassare il robot.

float x = 60; // coordinata X


float y = 440; // coordinata Y
int radius = 45; // Raggio della Testa
int bodyHeight = 160; // Altezza del Corpo
int neckHeight = 70; // Altezza del Collo
float easing = 0.02;
void setup() {
size(360, 480);
smooth();
strokeWeight(2);
ellipseMode(RADIUS);
}
void draw() {
int targetX = mouseX;
x += (targetX - x) * easing;
if (mousePressed) {
neckHeight = 16;
bodyHeight = 90;
} else {
neckHeight = 70;
bodyHeight = 160;
}
float ny = y - bodyHeight - neckHeight - radius;
background(204);
// Collo
stroke(102);
line(x+12, y-bodyHeight, x+12, ny);
// Antenne
line(x+12, ny, x-18, ny-43);
line(x+12, ny, x+42, ny-99);
line(x+12, ny, x+78, ny+15);
// Corpo
noStroke();
fill(102);
ellipse(x, y-33, 33, 33);
fill(0);
rect(x-45, y-bodyHeight, 90, bodyHeight-33);
// Testa
fill(0);
ellipse(x+12, ny, radius, radius);
fill(255);
ellipse(x+24, ny-6, 14, 14);
fill(0);
ellipse(x+24, ny-6, 3, 3);
}
6/Media

Processing capace di disegnare pi che semplici linee e forme.


arrivato il momento di imparare come caricare immagini raster,
file vettoriali, e font all'interno del nostro programma per
estendere le possibilit visuali alla fotografia , a diagrammi
dettagliati, e ai pi diversi caratteri tipografici.
Processing utilizza una cartella chiamata data per conservare questi file, cosicch non c' il bisogno
di pensare alla loro posizione quando creiamo uno Sketch che verr eseguito sul desktop, sul Web o
su di un dispositivo mobile. Abbiamo postato alcuni file multimediali online perch li usiate negli
esempi di questo capitolo: http://www.processing.org/learning/books/media.zip .

Scarica questo file, decomprimilo sul desktop ( o da qualsiasi altra parte che si pi comoda), e
prendi mentalmente nota della sua posizione.

NOTA: Per la decompressione su Mac OS X, basta fare doppio-click sul file, e verr creata una
cartella chiamata media. Su Windows, fai doppio-click sul file media.zip , che aprir una nuova
finestra. In questa finestra, trascina la cartella media sul desktop.

Crea un nuovo sketch, e seleziona Add File dal menu Sketch. Trova il file lunar.jpg dalla cartella
media che hai appena decompresso e selezionalo. Se tutto va per il verso giusto, nell'area dei
messaggi si legger 1 file added to the sketch.

Per controllare il file, selezionare Show Sketch folder nel menu Sketch. Dovresti vedere una cartella
chiamata data, con una copia di lunar.jpg all'interno. Quando aggiungi un file allo sketch, la cartella
data verr creata automaticamente. Invece di usare comando Add File dal menu, puoi ottenere la
stessa cosa trascinando i file all'interno dell'area di editor della finestra di Processing. I file saranno
copiati nella cartella data allo stesso modo ( e la cartella verr creata se non esisteva gi ).

Puoi anche creare la cartella data fuori da Processing e copiare qui i tuoi file da solo. Non avrai il
messaggio che ti dir che questi file sono stati aggiunti, ma questo un utile metodo quando stai
lavorando con un gran numero di file.

NOTA: Su Windows e Mac OS X, le estensioni dei file sono nascoste di default. una buona idea
cambiare questa impostazione cos che potrai sempre vedere l'intero nome dei tuoi file.
Su Mac OS X, seleziona Preferences dal menu Finder, e assicurati che
Show all filename extension selezionato nella tab Advanced. Su Windows, cerca Folder
Options ( Opzioni Cartella ) e selezionane qui l'opzione.

Immagini
Ci sono tre passi da seguire prima di poter disegnare un'immagine sullo schermo:

1. Aggiungere l'immagine nella cartella data dello sketch (le istruzioni sono state date in
precedenza)
2. Creare una variabile PImage per immagazzinare le immagini.
3. Caricare l'immagine nella variabile con loadImage( ).

Esempio 6-1: Caricare un'Immagine


Dopo che ogni passo stato effettuato, puoi disegnare l'immagine sullo schermo con la funzione
image( ) . Il primo parametro di image( ) specifica l'immagine da disegnare; il secondo ed il terzo
impostano le coordinate x ed y:

PImage img;
void setup() {
size(480, 120);
img = loadImage("lunar.jpg");
}
void draw() {
image(img, 0, 0);
}

I parametri quattro e cinque sono opzionali ed impostano l'altezza e la larghezza in cui verr
disegnata l'immagine.

Questi prossimi esempi mostrano come lavorare con pi di un'immagine nello stesso programma e
come ridimensionare un'immagine.

Esempio 6-2: Caricare pi di un'Immagine

per questo esempio, hai bisogno di aggiungere il file capsule.jpg ( che si trova nella cartella media
che hai scaricato ) al tuo sketch usando uno dei metodi spiegati prima.

PImage img1;
PImage img2;
void setup() {
size(480, 120);
img1 = loadImage("lunar.jpg");
img2 = loadImage("capsule.jpg");
}
void draw() {
image(img1, -120, 0);
image(img1, 130, 0, 240, 120);
image(img2, 300, 0, 240, 120);
}

Esempio 6-3: Usare il Mouse con le Immagini


Quando i valori di mouseX e mouseY sono usati come parte del quarto e quinto parametro della
funzione image( ) , la dimensione dell'immagine verr cambiata con il movimento del mouse:

PImage img;
void setup() {
size(480, 120);
img = loadImage("lunar.jpg");
}
void draw() {
background(0);
image(img, 0, 0, mouseX * 2, mouseY * 2);
}

NOTA: Quando un'immagine visualizzata pi grande o pi piccola del suo formato reale, pu
venire distorta. Fai attenzione nel preparare la tua immagine nella dimensione in cui sar utilizzata.
Quando il formato di visualizzazione dell'immagine viene cambiato con la funzione image( ),
l'immagine vera e propria sul disco rigido subisce modifiche.

Processing pu caricare e visualizzare immagini raster nei formati JPEG, PNG e GIF.
(le forme vettoriali nel formato SVG possono essere visualizzate in modo differente, come descritto
in Forme, in seguito in questo capitolo.) Puoi convertire le immagini nei formati JPEG,PNG e
GIF usando programmi come GIMP e Photoshop. La maggior parte delle fotocamere digitali
salvano immagini in JPEG, ma di solito c' bisogno di ridurne la grandezza prima di usarle con
Processing. Una tipica fotocamera digitale crea un'immagine che diverse volte pi grande dell'area
di disegno della maggioranza degli sketch di Processing, cos ridimensionare queste immagini
prima che siano aggiunte alla cartella data rende l'esecuzione degli sketch pi efficiente, e riparmia
spazio sul disco.

Le immagini GIF e PNG supportano la trasparenza, ci vuol dire che questi pixel possono essere
invisibili o parzialmente visibili (ricorda la discussione su color( ) e i valori alpha nelle pagine
26-29). Le immagini GIF hanno 1 bit di trasparenza, ovvero che i pixel sono o totalmente opachi o
completamente trasparenti. Le immagini PNG hanno 8 bit di trasparenza, ci comporta che ogni
pixel pu avere un livello variabile di trasparenza. L'esempio seguente mostra la differenza, usando
i file clouds.gif e clouds.png trovati nella cartella media che hai scaricato. Sii sicuro di aggiungerla
allo sketch prima di provare ogni esempio.

Esempio 6-4: Trasparenza con un GIF


PImage img;
void setup() {
size(480, 120);
img = loadImage("clouds.gif");
}
void draw() {
background(255);
image(img, 0, 0);
image(img, 0, mouseY * -1);
}

Esempio 6-5: Trasparenza con un PNG


PImage img;
void setup() {
size(480, 120);
img = loadImage("clouds.png");
}
void draw() {
background(204);
image(img, 0, 0);
image(img, 0, mouseY * -1);
}

NOTA: Ricorda di inserire l'estensione del file .gif , .jpg , o .png quando carichi l'immagine. Inoltre
assicurati che il nome dell'immagine stato scritto correttamente cos come appare nel file, anche se
le lettere sono maiuscole o minuscole. E se te la sei persa, leggi la nota precedente in questo
capitolo riguardo all'essere sicuri che l'estensione dei file sia visibile su Mac OS X e su Windows.

Font
Processing pu visualizzare il testo con font diversi da quello predefinito. Prima di poter
visualizzare il testo in un carattere differente, hai bisogno di convertire un font installato nel tuo
computer nel formato VLW, il quale memorizza ogni lettera come una piccola immagine. Per fare
ci, seleziona Create Font dal menu Tools per aprire la finestra di dialogo ( Figura 6-1 ). Specifica il
font che vuoi convertire, cos come la dimensione e se vuoi che sia smussato (anti-aliased).

NOTA: Seleziona attentamente la dimensione del font considerando ci che segue:


crea il font con la grandezza in cui preferisci usarlo nel tuo sketch (o pi largo), ma tieni in mente
che dimensioni pi grandi aumentano la dimensione del file. Seleziona l'opzione dei caratteri solo
se userai caratteri non romani come testi giapponesi o cinesi, poich anche questo aumenter la
grandezza del file significativamente.

Quando clicchi il pulsante OK nello strumento Create Font, il font VLW viene creato e posizionato
nella cartella data dello sketch. Ora possibile caricare il font e aggiungere parole allo sketch.
Questa parte simile a ci che accade lavorando con le immagini, ma con un passo ulteriore:

1. Aggiungi il font alla cartella data dello sketch (istruzioni date in precedenza).
2. Crea una variabile PFont per memorizzare il font.
3. Carica il font nella variabile con loadFont( ) .
4. Usa il comando textFont( ) per impostare il font corrente.

Esempio 6-6: Disegnare con i Font


Ora puoi disegnare queste lettere sullo schermo con la funzione text( ), e puoi cambiarne la
dimensione con textSize( ). Per questo esempio, hai bisogno di usare lo strumento Create Font per
creare un font VLW ( e modificare la riga loadFont( ) per usarlo), oppure puoi usare
AndaleMono-36.vlw dalla cartella media:

PFont font;
void setup() {
size(480, 120);
smooth();
font = loadFont("AndaleMono-36.vlw");
textFont(font);
}
void draw() {
background(102);
textSize(36);
text("Thats one small step for man...", 25, 60);
textSize(18);
text("Thats one small step for man...", 27, 90);
}

Il primo parametro di text( ) il carattere o i caratteri da tracciare sullo schermo.


(nota che i caratteri sono racchiuse all'interno delle virgolette.) Il secondo e terzo parametro imposta
la posizione orizzontale e verticale. La posizione relativa alla linea di base del testo (vedi Figura
6-2).

Esempio 6-7: Disegnare del Testo in un Riquadro


Puoi anche impostare il testo per disegnarlo all'interno di un riquadro aggiungendo i parametri
quattro e cinque che specificano l'altezza e la larghezza del riquadro:

PFont font;
void setup() {
size(480, 120);
font = loadFont("AndaleMono-24.vlw");
textFont(font);
}
void draw() {
background(102);
text("Thats one small step for man...", 26, 30, 240, 100);
}

Esempio 6-8: Immagazzinare del Testo in una Stringa


Nell'esempio precedente, le parole all'interno della funzione text( ) cominciano a rendere il codice
difficoltoso da leggere. Possiamo memorizzare queste parole in una variabile per rendere il codice
pi modulare. Il data type di String usato per immagazzinare dati di testo.
Questa una nuova versione dell'esempio precedente usando String:

PFont font;
String quote = "Thats one small step for man...";
void setup() {
size(480, 120);
font = loadFont("AndaleMono-24.vlw");
textFont(font);
}
void draw() {
background(102);
text(quote, 26, 30, 240, 100);
}

Esiste una serie di funzioni supplementari che influenzano il modo di come le lettere saranno
visualizzate sullo schermo. Queste sono spiegate, con esempi, nella categoria Typography delle
referenze di Processing.

Forme
Se hai fatto forme vettoriali con programmi come Inkscape o Illustrator, puoi caricarle all'interno di
Processing direttamente. Questo utile per forme che si preferisce non costruire con le funzioni di
disegno di Processing. Come per le immagini, devi aggiungerle al tuo sketch prima di poterle
caricare.

Ci sono tre passi per caricare e tracciare un file SVG:


1. Aggiungi un file SVG alla cartella data dello sketch.
2. Crea una variabile PShape per conservare il file vettoriale.
3. Carica il file vettoriale all'interno della variabile con LoadShape( ).

Esempio 6-9: Disegnare con le Forme


Una volta che hai seguito questi passaggi, puoi visualizzare l'immagine sullo schermo con la
funzione shape( ):

PShape network;
void setup() {
size(480, 120);
smooth();
network = loadShape("network.svg");
}
void draw() {
background(0);
shape(network, 30, 10);
shape(network, 180, 10, 280, 280);
}

I parametri per la funzione shape( ) sono simili ad image( ). Il primo parametro indica a shape( )
quale SVG va disegnata e i due consecutivi impostano la posizione. I parametri quattro e cinque
sono opzionali e impostano la larghezza e l'altezza.

Esempio 6-10: Ridimensionare le Forme


A differenza delle immagini raster, le forme vettoriali possono essere scalate in ogni dimensione
senza perdere di risoluzione. In questo esempio, la forma ridimensionata basandosi sulla variabile
mouseX, e la funzione shapeMode( ) viene usata per disegnare la forma dal centro, invece che dalla
posizione predefinita, l'angolo in alto a sinistra:

PShape network;
void setup() {
size(240, 120);
smooth();
shapeMode(CENTER);
network = loadShape("network.svg");
}
void draw() {
background(0);
float diameter = map(mouseX, 0, width, 10, 800);
shape(network, 120, 60, diameter, diameter);
}

NOTA: Esistono delle limitazioni sul tipo di file SVG che puoi caricare. Processing non supporta
tutte le caratteristiche dei file SVG. Vedi le referenze di Processing per PShape per maggiori
dettagli.
Robot 4: Media
A differenza dei robot creati con linee e rettangoli disegnati in Processing nei capitoli precedenti,
questi robot sono stati creati con un programma di disegno vettoriale. Per alcune forme, spesso pi
semplice puntare e cliccare in uno strumento software come Inkscape o Illustrator che definire le
forme con il codice.

Esiste un compromesso per selezionare una tecnica di creazione dell'immagine piuttosto che
un'altra. Quando le forme vengono definite in Processing, sono pi facilmente modificabili mentre
il programma in esecuzione. Se le forme sono definite da qualche altra parte e poi caricate
all'interno di Processing, i cambiamenti saranno limitati alla posizione, all'angolo, alla dimensione.
Quando ciascun robot viene caricato da un file SVG, come mostra l'esempio, le variazioni
caratterizzate in Robot 2 (vedi Robot 2: Variabili nel capitolo 4) sono impossibili.

Le immagini possono essere caricate all'interno di uno sketch per portare file visuali creati in altri
programmi o acquisite con una fotocamera. Grazie a questa immagine come sfondo, i nostri robot
sono intenti nell'esplorazione di forme di vita in Norvegia all'alba del Ventesimo secolo.

I file SVG e PNG usati in questo esempio possono essere scaricati da


http://www.processing.org/learning/books/media.zip .

PShape bot1;
PShape bot2;
PShape bot3;
PImage landscape;
float easing = 0.05;
float offset = 0;
void setup() {
size(720, 480);
bot1 = loadShape("robot1.svg");
bot2 = loadShape("robot2.svg");
bot3 = loadShape("robot3.svg");
landscape = loadImage("alpine.png");
smooth();
}
void draw() {
// Set the background to the "landscape" image; this image
// must be the same width and height as the program
background(landscape);
// Set the left/right offset and apply easing to make
// the transition smooth
float targetOffset = map(mouseY, 0, height, -40, 40);
offset += (targetOffset - offset) * easing;
// Disegna il robot di sinistra
shape(bot1, 85 + offset, 65);
//Disegna il robot di destra pi piccolo e ne da un contrasto minore
float smallerOffset = offset * 0.7;
shape(bot2, 510 + smallerOffset, 140, 78, 248);
// Disegna il robot pi piccolo e ne da un contrasto minore
smallerOffset *= -0.5;
shape(bot3, 410 + smallerOffset, 225, 39, 124);
}
7/Movimento
Come un flip book, l'animazione sullo schermo ottenuta
disegnando un'immagine, poi disegnare un'immagine leggermente
differente, poi un'altra, e cos via. L'illusione del movimento
fluido creata dalla persistenza della visione. Quando una serie di
immagini simili viene presentata ad un ritmo abbastanza veloce, i
nostri cervelli traducono queste immagini nel movimento.

Esempio 7-1: Osservare il Frame Rate


Per creare un movimento fluido, Processing prova ad eseguire il codice all'interno di draw( ) a 60
fotogrammi al secondo. Per confermare la frequenza dei fotogrammi, esegui questo programma e
controlla i valori stampati sulla Console. La variabile frameRate prende nota della velocit del
programma.

void draw() {
println(frameRate);
}

Esempio 7-2: Impostare il Frame Rate


La funzione FrameRate( ) cambia la velocit di esecuzione del programma. Per vederne il risultato,
togli la funzione commento dalle differenti versioni di frameRate( ) in questo esempio:

void setup() {
frameRate(30); // Thirty frames each second
//frameRate(12); // Twelve frames each second
//frameRate(2); // Two frames each second
//frameRate(0.5); // One frame every two seconds
}void draw() {
println(frameRate);
}

NOTA: Processing tenta di eseguire il codice a 60 fotogrammi al secondo, ma se questo richiede pi


di 1/60 di secondo per eseguire il metodo draw( ), il frame rate diminuir. La funzione frameRate( )
specifica solo la frequenza massima dei fotogrammi, e la frequenza reale per qualsiasi programma
dipende dal computer che eseguir il codice.
Velocit e Direzione
Per creare esempi di movimento fluido, usiamo una tipologia di dati chiamata float. Questa
tipologia di variabile memorizza numeri con cifre decimali, i quali forniscono maggiore risoluzione
quando si lavora con il movimento. Ad esempio, quando si utilizza ints (numeri interi), la velocit
minima in cui ti potrai muovere ad ogni fotogramma di un pixel alla volta (1,2,3,4,...), ma con
float, puoi muoverti alla lentezza che preferisci (1.01, 1.01, 1.02, 1.03,...).

Esempio 7-3: Muovere una Forma


L'esempio seguente fa muovere una forma da sinistra a destra aggiornando la variabile x:

int radius = 40;


float x = -radius;
float speed = 0.5;
void setup() {
size(240, 120);
smooth();
ellipseMode(RADIUS);
}
void draw() {
background(0);
x += speed; // Increase the value of x
arc(x, 60, radius, radius, 0.52, 5.76);
}

Quando eseguirai questo codice, noterai che la forma si muove oltre la parte destra dello schermo
quando il valore della varibile x diventer maggiore della larghezza dello schermo. Il valore di x
continuer a crescere, ma la forma non sar pi visibile.

Esempio 7-4: Girare Attorno


Ci sono molte alternative a questo comportamento, che possono essere scelte a seconda delle tue
preferenze. Per prima cosa, estenderemo il codice per mostrare come far tornare la forma al bordo
sinistro dello schermo dopo che essa scomparsa a destra. In questo caso immagina lo schermo
come un cilindro appiattito, con la forma che si muove all'esterno per tornare al punto si partenza:

int radius = 40;


float x = -radius;
float speed = 0.5;
void setup() {
size(240, 120);
smooth();
ellipseMode(RADIUS);
}
void draw() {
background(0);
x += speed; // Increase the value of x
if (x > width+radius) { // If the shape is off screen,
x = -radius; // move to the left edge
}
arc(x, 60, radius, radius, 0.52, 5.76);
}
In ogni ciclo del draw( ), il codice esegue un test per vedere se il valore della x andato oltre il
valore della larghezza dello schermo (aggiungendo il raggio della forma). Se questo accade,
impostiamo il valore della x con un segno negativo, in modo che se continua ad aumentare, apparir
sullo schermo da sinistra. Vedi la Figura 7-1 per un diagramma di questo funzionamento.

Esempio 7-5: Rimbalzare oltre il Muro


In questo esempio, estenderemo l'Esempio 7-3 affinch la forma cambi direzione quando colpisce
uno dei bordi, invece di girare attorno. Per far si che questo accada, aggiungiamo una nuova
variabile per memorizzare la direzione della forma.Un valore di direzione fa muovere la forma
verso destra, ed un valore di -1 muove la forma verso sinistra:

int radius = 40;


float x = 110;
float speed = 0.5;
int direction = 1;
void setup() {
size(240, 120);
smooth();
ellipseMode(RADIUS);
}
void draw() {
background(0);
x += speed * direction;
if ((x > width-radius) || (x < radius)) {
direction = -direction; // Flip direction
}
if (direction == 1) {
arc(x, 60, radius, radius, 0.52, 5.76); // Face right
} else {
arc(x, 60, radius, radius, 3.67, 8.9); // Face left
}
}

Quando la forma raggiunge un bordo, il codice inverte la direzione della forma cambiando il segno
della variabile direction. Ad esempio, se la variabile direction fosse positiva quando la forma
raggiunge uno dei bordi, il codice la inverte in negativa.

Interpolazione
A volte potresti voler animare una forma per farla andare da un punto dello schermo ad un altro.
Con poche linee di codice, puoi impostare il punto di partenza e la posizione finale, poi calcolare le
posizioni che sono nel mezzo (tween) ad ogni frame.

Esempio 7-6: Calcolare le Posizioni di Interpolazione


Per rendere modulare questo esempio di codice, abbiamo creato un gruppo di variabili in cima.
Esegui il codice diverse volte e cambiane i valori per vedere come pu muovere una forma da una
qualsiasi posizione ad un altra ad una serie di velocit:

int startX = 20; // Coordinata x iniziale


int stopX = 160; // Coordinata x finale
int startY = 30; // Coordinata y iniziale
int stopY = 80; // Coordinata y finale
float x = startX; // Coordinata x corrente
float y = startY; // coordinata y corrente
float step = 0.005; // Dimensione di ogni passaggio (0.0 to 1.0)
float pct = 0.0; // Percentuale percorsa (0.0 to 1.0)
void setup() {
size(240, 120);
smooth();
}
void draw() {
background(0);
if (pct < 1.0) {
x = startX + ((stopX-startX) * pct);
y = startY + ((stopY-startX) * pct);
pct += step;
}
ellipse(x, y, 20, 20);
}

Casualit
A differenza del movimento fluido e lineare comune alla computer graphic, il movimento nel
mondo fisico solitamente idiosincratico. Per fare un esempio, pensa ad una foglia che fluttua fino
al suolo, o ad una formica che striscia sul terreno ruvido. Possiamo simulare le imprevedibili
caratteristiche del mondo generando numeri casuali. La funzione random( )calcola questi valori;
possiamo impostare una gamma per sintonizzare l'ammontare di disordine in un programma.

Esempio 7-7: Generare Valori Casuali


Il breve esempio seguente stampa valori casuali sulla Console, con un intervallo limitato dalla
posizione del mouse. La funzione random( ) restituisce sempre un valore decimale, quindi sii sicuro
che la variabile sulla parte sinistra dell'operatore di assegnazione (=) decimale come quello
seguente:

void draw() {
float r = random(0, mouseX);
println(r);
}

Esempio7-8: Disegnare in Modo Casuale


L'esempio seguente costruito sull'esempio 7-7; usa i valori da random( ) per cambiare la posizione
delle linee sullo schermo. Quando il mouse a sinistra dello schermo, il cambiamento minimo;
come si muove sulla destra, i valori da random( ) crescono ed il movimento diviene pi evidente.
Poich la funzione random( ) all'interno del ciclo for, un nuovo valore casuale viene calcolato per
tutti i punti di ogni linea.

void setup() {
size(240, 120);
smooth();
}
void draw() {
background(204);
for (int x = 20; x < width; x += 20) {
float mx = mouseX / 10;
float offsetA = random(-mx, mx);
float offsetB = random(-mx, mx);
line(x + offsetA, 20, x - offsetB, 100);
}
}

Esempio 7-9: Muovere le Forme in Modo Casuale


Quando c' bisogno di muovere delle forme sullo schermo, i valori casuali possono generare
immagini che sono pi naturali nell'aspetto. Nell'esempio seguente, la posizione del cerchio viene
modificata da valori casuali in ogni ciclo del draw( ). poich la funzione background( ) non usata,
rimane traccia delle posizioni precedenti.

float speed = 2.5;


int diameter = 20;
float x;
float y;
void setup() {
size(240, 120);
smooth();
x = width/2;
y = height/2;
}
void draw() {
x += random(-speed, speed);
y += random(-speed, speed);
ellipse(x, y, diameter, diameter);
}

Se osservi abbastanza a lungo questo esempio, potrai notare che il cerchio lascia la finestra e poi
ritorna. Questo lasciato al caso, ma possiamo aggiungere alcune strutture if o usare la funzione
constrain( ) per non lasciare che il cerchio abbandoni lo schermo. La funzione constrain( ) limita un
valore ad una gamma predefinita, la quale pu essere usata per mantenere la x e la y all'interno dei
confini della finestra di visualizzazione. Sostituendo il draw( ) nell'esempio precedente con quello
seguente, sarai sicuro che l'ellisse rimarr all'interno dello schermo.

void draw() {
x += random(-speed, speed);
y += random(-speed, speed);
x = constrain(x, 0, width);
y = constrain(y, 0, height);
ellipse(x, y, diameter, diameter);
}

NOTA: La funzione randomSeed( ) pu essere usata per forzare la funzione random( ) a produrre la
stessa sequenza di numeri ogni volta che il programma viene eseguito. Questo aspetto descritto
pi approfonditamente nelle Reference di Processing.

Contatori
Ogni programma di Processing tiene conto dell'ammontare di tempo che passato dal momento in
cui stato fatto partire. Viene contato in millisecondi (la millesima parte di un secondo) , cos dopo
1 secondo, il contatore si trova a 1000; dopo 5 secondi, a 5000; e dopo un minuto, a 60000.
Possiamo usare questo contatore per innescare le animazioni in un momento specifico.
La funzione millis( ) riporta il valore del contatore.

Esempio 7-10: Il Tempo Passa


Puoi osservare il tempo passare quando esegui questo programma:

void draw() {
int timer = millis();
println(timer);
}

Esempio 7-11: Innescare Eventi a Tempo


Se abbinati con un blocco if, i valori da millis( ) possono essere utilizzati in sequenze animate ed
eventi all'interno di un programma. Per esempio, dopo che due secondi sono trascorsi, il codice
all'interno del blocco if pu innescare un cambiamento. In questo esempio, le variabili chiamate
time1 e time2 determinano quando il valore della variabile x dovr essere cambiato.

int time1 = 2000;


int time2 = 4000;
float x = 0;
void setup() {
size(480, 120);
smooth();
}
void draw() {
int currentTime = millis();
background(204);
if (currentTime > time2) {
x -= 0.5;
} else if (currentTime > time1) {
x += 2;
}
ellipse(x, 60, 90, 90);
}

Circolare

Se sei un asso della trigonometria, gi sai quanto siano stupefacenti le funzioni di seno e coseno.
Se non lo sei, speriamo che il prossimo esempio far scattare il tuo interesse. Non vogliamo parlare
dettagliatamente di matematica qui, ma mostreremo qualche applicazione per generare un
movimento fluido.

La figura 7-2 mostra un'immagine dei valori di un'onda sinusoidale e come si collegano agli angoli.
In cima ed in fondo all'onda, c' da notare come la frequenza di cambiamenti ( il cambiamento
nell'asse verticale ) rallenta, si ferma, poi cambia direzione. questa la qualit della curva che
genera un movimento interessante.

Le funzioni sin( ) e cos( ) in Processing riportano un valore tra -1 e 1 per il seno ed il coseno
dell'angolo specificato. Come arc( ), gli angoli devono essere dati in radianti (vedi l'Esempio 3-7 e
3-8 per un promemoria di come funzionano i radianti). Per facilit di disegno, i valori decimali
riportati da sin( ) e cos( ) sono di solito moltiplicati per raggiungere un valore pi grande.

Esempio 7-12: Valori dell'Onda Sinusoidale


Questo esempio mostra come i valori per la funzione sin( ) hanno un ciclo che va da -1 ad 1 quando
l'angolo aumenta. Con la funzione map( ), la variabile sinval viene convertita da questo intervallo ai
valori da 0 a 255. Questo nuovo valore viene usato per impostare il colore di sfondo della finestra:

float angle = 0.0;


void draw() {
float sinval = sin(angle);
println(sinval);
float gray = map(sinval, -1, 1, 0, 255);
background(gray);
angle += 0.1;
}

Esempio 7-13: Movimento dell'Onda Sinusoidale


Questo esempio mostra come questi valori possono essere convertiti in movimento:

float angle = 0.0;


float offset = 60;
float scalar = 40;
float speed = 0.05;
void setup() {
size(240, 120);
smooth();
}
void draw() {
background(0);
float y1 = offset + sin(angle) * scalar;
float y2 = offset + sin(angle + 0.4) * scalar;
float y3 = offset + sin(angle + 0.8) * scalar;
ellipse( 80, y1, 40, 40);
ellipse(120, y2, 40, 40);
ellipse(160, y3, 40, 40);
angle += speed;
}

Esempio 7-14: Moto Circolare


Quando sin( ) e cos( ) sono usati insieme, possono produrre il moto circolare. I valori del cos( )
forniscono le coordinate x, e i valori di sin( ) le coordinate y. Entrambi vengono moltiplicati da una
variabile chiamata scalar per cambiare il raggio del movimento e sommati con un valore di offset
per impostare il centro del movimento circolare:

float angle = 0.0;


float offset = 60;
float scalar = 30;
float speed = 0.05;
void setup() {
size(120, 120);
smooth();
}
void draw() {
float x = offset + cos(angle) * scalar;
float y = offset + sin(angle) * scalar;
ellipse( x, y, 40, 40);
angle += speed;
}
Esempio 7-15: Spirali
Un leggero cambiamento fatto per aumentare il valore di scalar ad ogni frame produce una spirale,
invece che un cerchio:

float angle = 0.0;


float offset = 60;
float scalar = 2;
float speed = 0.05;
void setup() {
size(120, 120);
fill(0);
smooth();
}
void draw() {
float x = offset + cos(angle) * scalar;
float y = offset + sin(angle) * scalar;
ellipse( x, y, 2, 2);
angle += speed;
scalar += speed;
}

Traslare, Ruotare, Scalare


Cambiare le coordinate dello schermo una tecnica alternativa per creare il movimento.
Ad esempio, puoi muovere una forma a destra per 50 pixel, oppure puoi muovere la posizione delle
coordinate (0,0) a destra per 50 pixel il risultato visivo sullo schermo sar lo stesso.
Modificando il sistema predefinito delle coordinate, possiamo creare diverse trasformazioni incluse
la traslazione, la rotazione, e il ridimensionamento. La figura 7-3 ne fa una dimostrazione grafica.
Lavorare con le trasformazioni pu essere complicato, ma la funzione translate( ) il metodo pi
lineare, quindi iniziamo con questo. Questa funzione pu cambiare il sistema di coordinate a destra,
a sinistra, in alto e in basso grazie a questi due parametri.

Esempio 7-16: Traslare la Posizione


In questo esempio, nota che ogni rettangolo disegnato alle coordinate (0,0), ma vengono spostati
in giro per lo schermo, poich sono condizionati da translate( ):

void setup() {
size(120, 120);
}
void draw() {
translate(mouseX, mouseY);
rect(0, 0, 30, 30);
}

La funzione translate( ) imposta le coordinate (0,0) dello schermo alla posizione del mouse.
Nella linea successiva, il rect( ) gi disegnato alle nuove coordinate (0,0) appunto ridisegnato
nella posizione del mouse.

Esempio 7-17: Traslazioni Multiple


Dopo che una trasformazione stata effettuata, questa viene applicata a tutte le funzioni di disegno
che seguono. Nota cosa succede quando un secondo comando traslate viene aggiunto per
controllare un secondo rettangolo:

void setup() {
size(120, 120);
}
void draw() {
translate(mouseX, mouseY);
rect(0, 0, 30, 30);
translate(35, 10);
rect(0, 0, 15, 15);
}

Il rettangolo pi piccolo stato traslato attraverso la somma di mouseX +35 e mouseY +10.

Esempio 7-18: Isolare le Trasformazioni


Per isolare gli effetti di una trasformazione cos da non dover influenzare i comandi successivi, usa
le funzioni pushMatrix( ) e popMatrix( ). Quando la funzione pushMatrix( ) viene eseguita, salva
una copia dell'attuale sistema di coordinate e lo rispristina dopo popMatrix( ):

void setup() {
size(120, 120);
}
void draw() {
pushMatrix();
translate(mouseX, mouseY);
rect(0, 0, 30, 30);
popMatrix();
translate(35, 10);
rect(0, 0, 15, 15);
}
In questo esempio, il rettangolo pi piccolo disegnato sempre nell'angolo in alto a sinistra perch
la funzione translate(mouseX,mouseY) viene cancellata da popMatrix( ).

NOTA: Le funzioni pushMatrix( ) e popMatrix( ) vengono sempre usate in coppia. Per ogni
pushMatrix( ), hai bisogno di avere un popMatrix( ) corrispondente.

Esempio 7-19: Rotazione

La funzione rotate( ) ruota il sistema di coordinate. Ha un solo parametro, cio l'angolo (in radianti)
da ruotare. Questo ruota sempre relazione a (0,0), che comunemente viene detto ruotare attorno
l'origine. Per far girare una forma attorno al suo punto centrale, prima di tutto usa translate( ) per
muoverlo nella posizione in cui preferisci che sia visualizzata la forma, poi richiama la funzione
rotate( ), ed infine disegna la forma con il suo centro in (0,0):

float angle = 0.0;


void setup() {
size(120, 120);
smooth();
}
void draw() {
translate(mouseX, mouseY);
rotate(angle);
rect(-15, -15, 30, 30);
angle += 0.1;
}
Esempio 7-20: Combinare Trasformazioni
Quando translate( ) e rotate( ) vengono combinate, l'ordine in cui appaiono influenza il risultato.
L'esempio seguente identico all'Esempio 7-19, eccetto che per translate( ) e rotate( ) che sono
invertite. La forma ora ruota attorno l'angolo in alto a sinistra nella finestra di visualizzazione, con
la distanza dall'angolo stabilita da translate( ) :

float angle = 0.0;


void setup() {
size(120, 120);
smooth();
}
void draw() {
rotate(angle);
translate(mouseX, mouseY);
rect(-15, -15, 30, 30);
angle += 0.1;
}

NOTA: Puoi anche usare le funzioni rectMode( ),ellipseMode( ),imageMode( ), e shapeMode( ) per
facilitare il disegno di forme a partire dal loro centro.

Esempio 7-21: Scalare


La funzione scale( ) estende le coordinate sullo schermo. Cos come rotate( ), trasforma a partire
dall'origine. Pertanto, cos come rotate( ), per scalare una forma a partire dal suo centro, opera una
traslazione dell'origine alla posizione determinata, ridimensiona la forma e poi disegnala con il
centro alle coordinate (0,0):

float angle = 0.0;


void setup() {
size(120, 120);
smooth();
}
void draw() {
translate(mouseX, mouseY);
scale(sin(angle) + 2);
rect(-15, -15, 30, 30);
angle += 0.1;
}

Esempio 7-22: Mantenere il Contorno Costante


Dalle linee spesse nell'Esempio 7-21, puoi osservare come la funzione scale( ) condizioni la
larghezza del contorno. Per mantenere costante la larghezza del contorno quando una forma viene
ridimensionata, dividi la larghezza desiderata del contorno per il valore scalare:

float angle = 0.0;


void setup() {
size(120, 120);
smooth();
}
void draw() {
translate(mouseX, mouseY);
float scalar = sin(angle) + 2;
scale(scalar);
strokeWeight(1.0 / scalar);
rect(-15, -15, 30, 30);
angle += 0.1;
}

Esempio 7-23: Un Braccio Articolato


In questo pi lungo esempio finale riguardante le trasformazioni, abbiamo messo insieme una serie
di funzioni rotate( ) e translate( ) per creare un braccio articolato che si piega avanti e indietro.
Ogni translate( ) in pi muove la posizione delle linee, ed ogni rotate( ) aggiunge alla rotazione
precedente per far si che si pieghi ancor di pi:

float angle = 0.0;


float angleDirection = 1;
float speed = 0.005;
void setup() {
size(120, 120);
smooth();
}
void draw() {
background(204);
translate(20, 25); // Move to start position
rotate(angle);
strokeWeight(12);
line(0, 0, 40, 0);
translate(40, 0); // Move to next joint
rotate(angle * 2.0);
strokeWeight(6);
line(0, 0, 30, 0);
translate(30, 0); // Move to next joint
rotate(angle * 2.5);
strokeWeight(3);
line(0, 0, 20, 0);
angle += speed * angleDirection;
if ((angle > QUARTER_PI) || (angle < 0)) {
angleDirection *= -1;
}
}

In questo caso, non usiamo un pushMatrix( ) o un popMatrix( ), poich vogliamo che le


trasformazioni si propaghino cos che ogni trasformazione venga costruita sopra l'ultima. Il
sistema di coordinate automaticamente resettato a quello predefinito quando draw( ) fa partire
ciascun frame.
Robot 5: Movimento
In questo esempio, le tecniche per il movimento casuale e circolare vengono applicate al robot.
Il background( ) viene eliminato per far si che sia pi facile vedere come cambiano la posizione ed
il corpo del robot.

Ad ogni frame, un numero casuale tra -4 e 4 aggiunto alla coordinata x, ed un numero casuale tra
-1 e 1 aggiunto alla coordinata y. Questo causer un movimento del robot maggiormente
direzionato da sinistra a destra che da sopra a sotto. I numeri calcolati dalla funzione sin( )
modificano l'altezza del collo cos da farlo oscillare tra un'altezza di 50 e 110 pixel:

float x = 180; // Coordinata-x


float y = 400; // Coordinata-y
float bodyHeight = 153; // Altezza del corpo
float neckHeight = 56; // Altezza del collo
float radius = 45; // Raggio della testa
float angle = 0.0; // Angolo per il movimento
void setup() {
size(360, 480);
smooth();
ellipseMode(RADIUS);
background(204);
}
void draw() {
// Cambia posizione tramite un piccolo numero casuale
x += random(-4, 4);
y += random(-1, 1);
// Cambia altezza del collo
neckHeight = 80 + sin(angle) * 30;
angle += 0.05;
// Regola l'altezza della testa
float ny = y - bodyHeight - neckHeight - radius;
// Collo
stroke(102);
line(x+2, y-bodyHeight, x+2, ny);
line(x+12, y-bodyHeight, x+12, ny);
line(x+22, y-bodyHeight, x+22, ny);
// Antenne
line(x+12, ny, x-18, ny-43);
line(x+12, ny, x+42, ny-99);
line(x+12, ny, x+78, ny+15);
// Corpo
noStroke();
fill(102);
ellipse(x, y-33, 33, 33);
fill(0);
rect(x-45, y-bodyHeight, 90, bodyHeight-33);
fill(102);
rect(x-45, y-bodyHeight+17, 90, 6);
// Testa
fill(0);
ellipse(x+12, ny, radius, radius);
fill(255);
ellipse(x+24, ny-6, 14, 14);
fill(0);
ellipse(x+24, ny-6, 3, 3);
}
8/Funzioni
Le funzioni sono i blocchi di costruzione di base per i programmi
di Processing. Sono apparse in ogni dimostrazione che abbiamo
presentato. Per esempio, abbiamo usato frequentemente la
funzione size( ), la funzione line( ), e la funzione fill( ).
Questo capitolo mostra come scrivere nuove funzioni per
estendere le capacit di Processing oltre le sue funzionalit
integrate.
La forza delle funzioni la modularit. Le funzioni sono unit di software indipendente che
vengono usate per costruire programmi pi complessi come i mattoncini LEGO, dove ogni tipo di
mattoncino ha un compito preciso, e costruire un modello complesso richiede l'utilizzo di parti
differenti combinate assieme. Cos come nelle funzioni, il vero potere di questi mattoni l'abilit di
costruire molte forme differenti dalla stessa serie di elementi. Lo stesso gruppo di LEGO che forma
un'astronave pu essere riutilizzata per costruire un camion, un grattacielo, e molti altri oggetti.

Le funzioni sono utili se vuoi disegnare una forma complessa come un albero pi e pi volte.
La funzione per disegnare un albero dovrebbe esser fatta da comandi integrati di Processing, come
line( ), che creano la forma. Dopo aver scritto il codice per costruire l'albero, non hai pi bisogno di
pensare di nuovo ai dettagli per disegnare l'albero puoi semplicemente scrivere albero( ) (o
qualsiasi nome tu abbia usato per la funzione) per disegnare la forma. Le funzioni consentono di
poter astrarre una sequenza complessa di dichiarazioni, cos da poter concentrarsi sull'obiettivo di
livello pi alto ( come disegnare un albero ), e non sui dettagli delle implementazioni ( il comando
line( ) che definisce la forma). Una volta che una funzione stata definita, il codice all'interno della
funzione non ha bisogno di essere ripetuto di nuovo.

Funzioni di Base
Un computer esegue un programma una riga alla volta. Quando una funzione viene eseguita, il
computer salta direttamente dove la funzione viene definita ed esegue il codice che vi si trova, poi
torna indietro dove si era interrotto.

Esempio 8-1: Tirare i Dadi


Questo funzionamento illustrato con la funzione rollDice( ) scritta per questo esempio. Quando un
programma parte, esegue il codice in setup( ) e si ferma. Il programma prende una deviazione ed
esegue il codice all'interno di rollDice( ) ogni volta che appare:

void setup() {
println("Ready to roll!");
rollDice(20);
rollDice(20);
rollDice(6);
println("Finished.");
}
void rollDice(int numSides) {
int d = 1 + int(random(numSides));
println("Rolling... " + d);
}

Le due righe di codice in rollDice( ) selezionano un numero casuale tra 1 ed il numero di facce del
dado, e stampa questo numero sulla Console. Poich il numero casuale, vedrai numeri differenti
ogni volta che il programma viene eseguito:

Ready to roll!
Rolling... 20
Rolling... 11
Rolling... 1
Finished.

Ogni volta che la funzione rollDice( ) viene eseguita all'interno del setup( ), il codice nella funzione
viene eseguito da cima a fondo, poi il programma continua sulla linea successiva nel setup( ).

La funzione random( ) (descritta a pagina 97) riporta un numero che va da 0 al numero specificato
(ma senza includerlo) . Cos random(6) riporta un numero tra 0 e 5.99999.... Siccome random( )
restituisce un valore decimale, usiamo anche int( ) per convertirlo in un valore intero. Cos
int(random(6)) restituir 0,1,2,3,4 o 5. Poi aggiungiamo 1 cos che il numero riportato vada da 1 a 6
(come un dado). Come in molti altri casi in questo libro, partire il conteggio da 0 rende pi facile
l'utilizzo del risultato di random( ) con altri calcoli.

Esempio 8-2: Un Altro Modo per Tirare i Dadi


Se un programma equivalente fosse scritto senza la funzione rollDice( ), potrebbe apparire in questo
modo:

void setup() {
println("Ready to roll!");
int d1 = 1 + int(random(20));
println("Rolling... " + d1);
int d2 = 1 + int(random(20));
println("Rolling... " + d2);
int d3 = 1 + int(random(6));
println("Rolling... " + d3);
println("Finished.");
}

La funzione rollDice( ) nell'Esempio 8-1 rende il codice pi semplice da leggere e conservare. Il


programma appare pi chiaro, perch il nome della funzione afferma con chiarezza la sua funzione.
In questo esempio, vediamo la funzione random( ) in setup( ), ma la sua utilit non cos ovvia. Il
numero delle facce del dado chiarito con una funzione: quando il codice dice rollDice(6), ovvio
che sta simulando il lancio di un dado a sei facce. Inoltre, l'Esempio 8-1 pi facile da conservare,
poich le informazioni non sono ripetute. La fase di rolling... viene ripetuta tre volte. Se
desideri cambiare questo testo in un altro, hai bisogno di aggiornare il programma in tre parti,invece
di fare una singola correzione all'interno della funzione rollDice( ). In aggiunta, come hai visto
nell'Esempio 8-5, una funzione pu anche rendere un programma pi corto (e quindi pi facile da
mantenere e leggere), che aiuta a ridurre il potenziale numero di bug.

Creare una Funzione

In questa sezione, disegneremo un gufo per esporre i passi coinvolti nella creazione di una funzione.

Esempio 8-3: Disegnare un Gufo


Per prima cosa disegniamo il gufo senza usare una funzione:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
translate(110, 110);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Body
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Left eye dome
ellipse(17.5, -65, 35, 35); // Right eye dome
arc(0, -65, 70, 70, 0, PI); // Chin
fill(0);
ellipse(-14, -65, 8, 8); // Left eye
ellipse(14, -65, 8, 8); // Right eye
quad(0, -58, 4, -51, 0, -44, -4, -51); // Beak
}

Nota che translate( ) viene usato per spostare l'origine (0,0) per 110 pixel a destra e 110 pixel verso
il basso. Poi il gufo viene disegnato relativamente a (0,0), con le sue coordinate a volte positive e a
volte negative,come se fosse centrato sul nuovo punto (0,0). Vedi la Figura 8-1.

Esempio 8-4: In due si in compagnia


Il codice presentato nell'Esempio 8-3 ragionevole se c' solamente un gufo, ma quando ne
disegnamo un secondo, la lunghezza del codice viene quasi duplicata:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
// Left owl
translate(110, 110);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Corpo
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Cupola dell'occhio sinistro
ellipse(17.5, -65, 35, 35); // Cupola dell'occhio destro
arc(0, -65, 70, 70, 0, PI); // Mento
fill(0);
ellipse(-14, -65, 8, 8); // Occhio sinistro
ellipse(14, -65, 8, 8); // Occhio destro
quad(0, -58, 4, -51, 0, -44, -4, -51); // Becco
// Gufo di destra
translate(70, 0);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Corpo
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Cupola dell'occhio sinistro
ellipse(17.5, -65, 35, 35); // Cupola dell'occhio destro
arc(0, -65, 70, 70, 0, PI); // Mento
fill(0);
ellipse(-14, -65, 8, 8); // Occhio sinistro
ellipse(14, -65, 8, 8); // Occhio destro
quad(0, -58, 4, -51, 0, -44, -4, -51); // Becco
}

Il programma cresciuto da 21 righe a 34 righe, poich il codice servito per disegnare il primo gufo
stato tagliato ed incollato nel programma ed un translate( ) stato inserito per muoverlo di 70
pixel a destra. Questo un metodo noioso ed inefficiente per disegnare un secondo gufo, senza
menzionare il mal di testa causato dall'aggiungere un terzo gufo con questo metodo. Ma duplicare il
codice non necessario, poich questo il tipo di situazione in cui una funzione pu venirci in
aiuto.

Esempio 8-5: Una Funzione Gufo


In questo esempio, una funzione viene introdotta per disegnare due gufi con lo stesso codice. Se
creiamo il codice che disegna il gufo sullo schermo in una nuova funzione, il codice ha bisogno solo
di apparire una volta nel programma:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
owl(110, 110);
owl(180, 110);
}
void owl(int x, int y) {
pushMatrix();
translate(x, y);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65); // Corpo
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35); // Cupola dell'occhio sinistro
ellipse(17.5, -65, 35, 35); // Cupola dell'occhio destro
arc(0, -65, 70, 70, 0, PI); // Mento
fill(0);
ellipse(-14, -65, 8, 8); // Occhio sinistro
ellipse(14, -65, 8, 8); // Occhio destro
quad(0, -58, 4, -51, 0, -44, -4, -51); // Becco
popMatrix();
}

Puoi osservare dall'illustrazione che questo esempio e l'Esempio 8-4 hanno lo stesso risultato, ma
questo esempio pi breve, poich il codice per disegnare il gufo appare solamente una volta,
all'interno della funzione nominata appropriatamente owl( ). Questo codice viene eseguito due
volte, perch richiamato per due volte all'interno di draw( ). Il gufo disegnato in due posizioni
differenti a causa dei parametri all'interno della funzione che imposta le coordinate x ed y.
I parametri sono una parte importante delle funzioni, perch garantiscono flessibilit. Abbiamo visto
un'altro esempio nella funzione rollDice( ); il singolo parametro nominato numSides rende possibile
la simulazione di un dado a sei facce, a 20 facce, a di un dado con un qualsiasi numero di facce.
Questo proprio come molte altre funzioni di Processing. Per esempio,i parametri nella funzione
line( ) rendono possibile disegnare una linea da un qualsiasi pixel dello schermo ad un altro pixel.
Senza i parametri, la funzione sarebbe stata abilitata a disegnare una linea solo da un punto fisso ad
un altro.

Ogni parametro possiede un data type (come int o float ) , poich ciascun parametro una variabile
che viene creata ogni volta che la funzione viene eseguita. Quando questo esempio viene eseguito,
la prima volta che la funzione gufo viene richiamata, il valore del parametro x 110, ed y anche
110. Nel secondo uso della funzione, il valore di x 180 ed y di nuovo 110. Ogni valore che passa
attraverso la funzione e poi ovunque appare il nome della variabile all'interno della funzione, viene
rimpiazzato con il valore in entrata.

Assicurati che i valori che passano all'interno di una funzione corrispondano ai data types dei
parametri. Come dimostrazione, se la riga seguente apparisse all'interno di setup( )
nell'Esempio 8-5:

owl(110.5, 120.2);

Questo causerebbe un errore, poich il data type per i parametri x e y int, ed i valori 110,5 e 120,2
sono valori decimali.

Esempio 8-6: Accrescere la Popolazione


Ora che abbiamo una funzione di base per disegnare il gufo ad una qualsiasi posizione, possiamo
disegnare molti gufi in modo efficiente posizionando la funzione all'interno di un ciclo for e
cambiando il primo parametro ad ogni ciclo.

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
for (int x = 35; x < width + 70; x += 70) {
owl(x, 110);
}
}
// Inserisci la funzione owl() Dall'Esempio 8-5

possibile aggiungere pi e pi parametri alla funzione per cambiare differenti aspetti di come il
gufo sar disegnato. I valori potrebbero essere inseriti per cambiare il colore del gufo, la rotazione,
la dimensione, o il diametro dei suoi occhi.

Esempio 8-7: Gufi di Dimensioni Differenti


In questo esempio, abbiamo aggiunto due parametri per cambiare il valore di grigio e la dimensione
di ciascun gufo:

void setup() {
size(480, 120);
smooth();
}
void draw() {
background(204);
randomSeed(0);
for (int i = 35; i < width + 40; i += 40) {
int gray = int(random(0, 102));
float scalar = random(0.25, 1.0);
owl(i, 110, gray, scalar);
}
}
void owl(int x, int y, int g, float s) {
pushMatrix();
translate(x, y);
scale(s); // Imposta la dimensione
stroke(g); // Imposta il valore di grigio
strokeWeight(70);
line(0, -35, 0, -65); // Corpo
noStroke();
fill(255-g);
ellipse(-17.5, -65, 35, 35); // Cupola dell'occhi sinistro
ellipse(17.5, -65, 35, 35); // Cupola dell'occhio destro
arc(0, -65, 70, 70, 0, PI); // Mento
fill(g);
ellipse(-14, -65, 8, 8); // Occhio sinistro
ellipse(14, -65, 8, 8); // Occhio destro
quad(0, -58, 4, -51, 0, -44, -4, -51); // Becco
popMatrix();
}

Restituire Valori
Le funzioni possono operare un calcolo e poi riportare un valore al programma principale. Abbiamo
gi utilizzato delle funzioni di questo tipo, incluse random( ) e sin( ). Nota che quando appaiono
questo tipo di funzioni, il valore di ritorno di solito assegnato ad una variabile:

float r = random(1, 10);

In questo caso, random( ) riporta un valore tra 1 e 10, che viene poi assegnato alla variabile r.

Una funzione che riporta un valore inoltre frequentemente usata come parametro per un'altra
funzione. Ad esempio:

point( random(width), random(height));


In questo caso, i valori da random( ) non sono assegnati ad una variabile sono passati come
parametri per point( ) ed usati per posizionare il punto all'interno della finestra.

Esempio 8-8: Restituire un Valore


Per creare una funzione che renda un valore, sostituisci la parola chiave void con il genere di dati
che vuoi che la funzione riporti. Nella tua funzione, specifica i dati che devono essere segnalati con
la parola chiave return. Per fare una prova, questo esempio include una funzione chiamata
calculateMars( ) che calcola il peso di una persona o di un oggetto sul nostro pianeta vicino:

void setup() {
float yourWeight = 132;
float marsWeight = calculateMars(yourWeight);
println(marsWeight);
}
float calculateMars(float w) {
float newWeight = w * 0.38;
return newWeight;
}
Da notare che il tipo di dati float situato prima del nome della funzione per mostrare che riporta un
valore decimale, e l'ultima riga del blocco, che riporta la variabile newWeight. Nella seconda linea
di setup( ), questo valore viene assegnato alla variabile marsWeight. (Per controllare il tuo peso su
Marte, scambia il valore della variabile yourWeight con il tuo peso.)
Robot 6: Funzioni
In contrasto con Robot 2 (vedi Robot 2: Variabili nel capitolo 4), questo esempio utilizza una
funzione per disegnare quattro variazioni di robot all'interno dello stesso programma. Siccome la
funzione drawRobot( ) appare quattro volte nel draw( ), il codice nel blocco drawRobot( ) viene
eseguito quattro volte, ogni volta con un diverso gruppo di parametri per cambiare la posizione e
l'altezza del corpo del robot.

Nota il modo in cui stato isolato il posto in cui si trovavano le variabili globali in Robot 2
all'interno della funzione drawRobot( ). poich queste variabili sono applicate solo per disegnare il
robot, si trovano all'interno delle parentesi graffe che definiscono il blocco della funzione
drawRobot( ). Siccome il valore della variabile radius non viene cambiato, non c' bisogno che esso
diventi un parametro. invece definito all'inizio di drawRobot( ):

void setup() {
size(720, 480);
smooth();
strokeWeight(2);
ellipseMode(RADIUS);
}
void draw() {
background(204);
drawRobot(120, 420, 110, 140);
drawRobot(270, 460, 260, 95);
drawRobot(420, 310, 80, 10);
drawRobot(570, 390, 180, 40);
}

void drawRobot(int x, int y, int bodyHeight, int neckHeight) {


int radius = 45;
int ny = y - bodyHeight - neckHeight - radius;

// Collo
stroke(102);
line(x+2, y-bodyHeight, x+2, ny);
line(x+12, y-bodyHeight, x+12, ny);
line(x+22, y-bodyHeight, x+22, ny);

// Antenne
line(x+12, ny, x-18, ny-43);
line(x+12, ny, x+42, ny-99);
line(x+12, ny, x+78, ny+15);

// Corpo
noStroke();
fill(102);
ellipse(x, y-33, 33, 33);
fill(0);
rect(x-45, y-bodyHeight, 90, bodyHeight-33);
fill(102);
rect(x-45, y-bodyHeight+17, 90, 6);

// Testa
fill(0);
ellipse(x+12, ny, radius, radius);
fill(255);
ellipse(x+24, ny-6, 14, 14);
fill(0);
ellipse(x+24, ny-6, 3, 3);
fill(153);
ellipse(x, ny-8, 5, 5);
ellipse(x+30, ny-26, 4, 4);
ellipse(x+41, ny+6, 3, 3);
}
9/Oggetti
La programmazione ad oggetti (Object-oriented programming,
OOP) un modo differente di pensare i tuoi programmi. Sebbene
il termine object-oriented programming pu suonare
intimidatorio, c' una buona notizia: stai lavorando con gli oggetti
fin dal Capitolo 6, quando hai iniziato ad usare PImage, PFont,
String, e PShape. A differenza dei generi di dati primitivi come
boolean, int, e float, che possono conservare solo un valore, un
oggetto ne pu immagazzinare diversi. Ma questa solamente una
parte della storia. Gli oggetti sono anche un modo di raggruppare
variabili con le relative funzioni. Siccome gi conosci il modo di
lavorare con le variabili e con le funzioni, gli oggetti
semplicemente combinano tutto ci che hai gi imparato in un
pacchetto pi comprensibile.
Gli oggetti sono importanti, perch spezzettano le idee in piccoli blocchi di costruzione. Questo
riflette il mondo naturale dove, per esempio, gli organi sono fatti di tessuto, il tessuto fatto di
cellule, e cos via. Similmente, come il tuo codice diventa pi complesso, devi cominciare a pensare
in termini di piccole strutture che ne formano altre pi complicate. pi semplice scrivere e
conservare piccoli e comprensibili pezzi di codice che lavorano assieme piuttosto che scrivere una
grande parte di codice che fa tutto quanto in una volta.

Un oggetto software una collezione di variabili e funzioni messe in relazione. Nel contesto degli
oggetti, una variabile chiamata campo, field ( o variabile istanza) ed una funzione chiamata
metodo, method. Campi e metodi lavorano proprio come le variabili e le funzioni spiegate nei
capitoli precedenti, ma useremo i nuovi termini per enfatizzare il fatto che esse sono parti di un
oggetto. Per dirlo in un altro modo, un oggetto combina i dati correlati (fields) con le azioni ed i
comportamenti correlati (metodi). L'idea di raggruppare insieme i relativi dati con i relativi metodi
che agiscono su quei dati.

Per esempio, per creare un modello di una radio, pensa ai parametri che possono essere regolati ed
alle azioni che possono condizionare questi parametri:

Campi: volume, frequenza, banda (FM,AM), energia (on,off)


Metodi: regolaVolume, regolaFrequenza, regolaBanda

Creare il modello di un semplice dispositivo meccanico semplice se paragonato al creare il


modello di un organismo come una formica od una persona. Non possibile ridurre questi
organismi complessi ad alcuni campi e metodi, ma possibile creare un modello che sia abbastanza
per dare una simulazione interessante. Il videogame The Sims ne un chiaro esempio. Questo gioco
funziona gestendo le attivit giornaliere di persone simulate. I personaggi hanno abbastanza
personalit per fare un videogame giocabile e accattivante, ma niente di pi. Infatti, questi hanno
solamente cinque attributi di personalit: acuto, espansivo, energico, scherzoso, e bello. Con la
conoscenza che possibile creare un modello altamente semplificato di organismi complessi,
possiamo iniziare a programmare una formica con solamente pochi campi e metodi:

Campi: tipo (operaio,soldato), peso, lunghezza


Metodi: cammina, pizzica, rilasciaFeromoni, mangia

Se fai una lista dei campi e metodi di una formica, si potrebbe scegliere se concentrarsi su differenti
aspetti del modello della formica. Non c' un modo giusto per creare un modello, sei tu che scegli il
metodo pi appropriato per il proposito dell'obiettivo del tuo programma.

Classi ed Oggetti
Prima di poter creare un oggetto, devi definire una classe. Una classe la specificazione per un
oggetto. Per usare un'analogia architettonica, una classe come il progetto di una casa, e l'oggetto
la casa in se stessa. Ogni casa fatta a partire dal progetto pu avere variazioni, ed il progetto
solamente la specificazione, non la struttura costruita. Ad esempio, una casa pu essere rossa ed
un'altra verde; una casa potrebbe avere il caminetto ed un'altra no. Proprio come con gli oggetti, la
classe definisce il genere di dati ed i comportamenti, ma ogni oggetto (casa) costruito da una
singola classe (progetto) ha delle variabili (colore,caminetto) che sono inpostati in valori differenti.
Per usare un termine pi tecnico, ogni oggetto un'istanza di una classe ed ogni istanza ha il
proprio gruppo di campi e metodi.

Definire una Classe


Prima che tu cominci a scrivere una classe, raccomandiamo una piccola pianificazione. Pensa ai
campi ed ai metodi che la tua classe dovrebbe avere. Fai un piccolo brainstorming per immaginare
tutte le opzioni possibili e poi fai delle priorit e cerca la tua ipotesi migliore su quello che potr
funzionare. Farai cambiamenti durante il processo di programmazione, ma importante avere un
buon punto di partenza.

Per i tuoi campi, seleziona nomi chiari e decidi i tipi di dati per ognuno. I campi all'interno di una
classe possono essere di ogni tipologia di dati. Una classe pu nello stesso tempo contenere diverse
booleane, valori decimali, immagini, stringhe, e cos via. Tieni a mente che una ragione di creare
una classe di raggruppare insieme elementi di dati correlati. Per i tuoi metodi, seleziona nomi
altrettanto chiari e decidi i valori da restituire (se c' n' bisogno). I metodi sono usati per cambiare i
valori dei campi e per svolgere azioni basate sui valori dei campi.

Per la tua prima classe, convertiremo l'Esempio 7-9 precedentemente mostrato in questo libro.
Partiremo facendo una lista dei campi da questo esempio:

float x
float y
int diameter
float speed
Il prossimo passo sar quello di capire quali metodi potrebbero essere utili per la classe.
Guardando all'interno della funzione draw( ) dall'esempio che stiamo adattando, vediamo due
componenti primarie. La posizione della forma aggiornata e disegnata sullo schermo. Creiamo
due metodi per la nostra classe, uno per ogni compito:

void move()
void display()

Nessuno di questi metodi riporta un valore, cos entrambi hanno il tipo di valore di ritorno come
void. La prossima volta che scriveremo la classe basandosi sulla lista di campi e metodi, seguiremo
quattro passaggi:

1. Creare il blocco.
2. Aggiungere i campi.
3. Scrivere un constructor (sar spiegato a breve) per assegnare i valori ai campi.
4. Aggiungere i metodi.

Prima di tutto, creiamo un blocco:

class jitterBug {

Nota che la parola chiave class in minuscolo ed il nome jitterBug in maiuscolo. Nominare le
classi con lettera maiuscola non richiesto, ma una convenzione ( che noi incoraggiamo
fortemente) usata per denotare che si tratta di una classe. ( La parola chiave class, d'altronde,
dev'essere minuscola perch una regola del linguaggio di programmazione.)

Secondo, aggiungiamo i campi. Quando lo facciamo, dobbiamo decidere quali campi avranno i loro
valori assegnati attraverso un constructor, un metodo speciale usato per questo scopo. In linea di
massima, i valori dei campi che tu desideri siano diversi per ogni classe vengono passati attraverso
il constructor, e gli altri valori dei campi possono essere definiti quando vengono dichiarati. Per la
classe jitterBug, abbiamo deciso che i valori per x, y e diameter saranno inseriti nel constructor.
Quindi i campi sono dichiarati come segue:

class JitterBug {
float x;
float y;
int diameter;
float speed = 0.5;
}

Terzo, aggiungiamo il costruttore. Il constructor ha sempre lo stesso nome della classe. L'obiettivo
del costruttore di assegnare i valori iniziali ai campi quando un oggetto (l'istanza di una classe)
viene creato (Figura 9-1). Il codice all'interno del blocco del costruttore viene eseguito una volta
quando un oggetto inizialmente creato. Come abbiamo detto prima, quando l'oggetto viene
inizializzato, immettiamo tre parametri nel costruttore. Ognuno di questi valori assegnato ad una
variabile temporanea che esiste solo mentre il codice all'interno del costruttore viene eseguito.
Per chiarire, abbiamo aggiunto il nome temp ad ognuna di queste variabili, ma possono essere
nominate con qualunque termine tu preferisca. Questi sono usati solamente per assegnare i valori ai
campi che sono parte della classe. Inoltre nota che il costruttore non riporta mai un valore e pertanto
non ha void qualunque altro genere di dati posto prima. Dopo aver aggiunto il costruttore, la classe
avr quest'aspetto:

class JitterBug {
float x;
float y;
int diameter;
float speed = 0.5;
JitterBug(float tempX, float tempY, int tempDiameter) {
x = tempX;
y = tempY;
diameter = tempDiameter;
}
}

Nell'ultimo passaggio si tratta di aggiungere i metodi. Questa parte lineare; proprio come
scrivere delle funzioni, ma qui sono contenute all'interno di una classe. Inoltre, nota la spaziatura
del codice. Ogni riga all'interno della classe ha un'indentazione di alcuni spazi per mostrare che si
trova all'interno del blocco. All'interno del constructor e dei metodi, il codice spaziato di nuovo
per mostrare chiaramente la gerarchia:

class JitterBug {

float x;
float y;
int diameter;
float speed = 2.5;

JitterBug(float tempX, float tempY, int tempDiameter) {


x = tempX;
y = tempY;
diameter = tempDiameter;
}

void move() {
x += random(-speed, speed);
y += random(-speed, speed);
}

void display() {
ellipse(x, y, diameter, diameter);
}

Esempio 9-1: Costruire un Oggetto


Ora che hai definito una classe, per usarla in un programma devi definire un oggetto da questa
classe. Ci sono due passaggi per creare un oggetto:

1. Dichiara la variabile oggetto.


2. Crea (inizializza) l'oggetto con la parola chiave new.

Partiremo dal mostrare come questo funzioni all'interno dello sketch di Processing e poi
continueremo con lo spiegare ogni parte nel dettaglio:

JitterBug bug; // Dichiara l'oggetto


void setup() {
size(480, 120);
smooth();
// Crea un oggetto ed inserisci i parametri
bug = new JitterBug(width/2, height/2, 20);
}
void draw() {
bug.move();
bug.display();
}
// Inserisci qui una copia della classe JitterBug

Ogni classe una tipologia di dati ed ogni oggetto una variabile. Dichiariamo le variabili oggetto
in modo simile alle variabili con tipi di dati primitivi come boolean, int, e float. L'oggetto viene
dichiarato affermando il genere di dati seguito da un nome per la variabile:

JitterBug bug;

Il secondo passo si inizializza l'oggetto con la parola chiave new. Questo crea spazio per l'oggetto in
memoria e crea i campi. Il nome del constructora destra della parola chiave new, seguita dai
parametri all'interno del constructor, se ce ne sono:

JitterBug bug = new JitterBug ( 200.0, 250.0, 30);

I tre numeri all'interno delle parentesi sono i parametri che vengono inseriti all'interno del
constructor della classe JitterBug. Il numero di questi parametri e la loro tipologia di dati devono
corrispondere a quelli del constructor.

Esempio 9-2: Creare Oggetti Multipli


Nell' Esempio 9-1, osserviamo qualcosa di nuovo: il punto che viene utilizzato per accedere ai
metodi dell'oggetto all'interno di draw( ) . Il punto usato per unire il nome dell'oggetto con i suoi
campi e metodi. Ci diventa chiaro in questo esempio, dove due oggetti sono costruiti a partire dalla
stessa classe. Il comando jit.move( ) si riferisce al metodo move( ) che appartiene all'oggetto
chiamato jit, e bug.move( ) si riferisce al metodo move( ) che appartiene all'oggetto chiamato bug:

JitterBug jit;
JitterBug bug;
void setup() {
size(480, 120);
smooth();
jit = new JitterBug(width * 0.33, height/2, 50);
bug = new JitterBug(width * 0.66, height/2, 10);
}
void draw() {
jit.move();
jit.display();
bug.move();
bug.display();
}
// Inserisci qui una copia della classe JitterBug

Ora che la classe esiste come proprio modulo di codice, ogni cambiamento modificher l'oggetto da
cui stato fatto. Per esempio, potresti aggiungere un campo alla classe JitterBug che controlla il
colore, oppure un'altra che determina la sua dimensione. Questi valori possono essere approvati
usando un constructor oppure assegnati utilizzando metodi addizionali, come setColor( ) o
setSize( ). E siccome si tratta di un'unit autonoma, puoi anche utilizzare la classe JitterBug in un
altro sketch.

Ora un buon momento per conoscere la funzione delle schede nell'ambiente di Processing (Figura
9-2). Le schede ti permettono di distribuire il tuo codice in pi di un file. Questo rende un codice
pi lungo pi facile da curare ed in generale pi maneggevole. Di solito viene creata una nuova
scheda per ciascuna classe, la quale rinforza la modularit del lavoro con le classi e rende il codice
pi semplice da reperire.

Per creare una nuova scheda, clicca sulla freccia nella parte destra della barra delle schede. Quando
selezioni New Tab dal menu, ti verr richiesto di dare un nome alla scheda nella finestra di avviso.
Utilizzando questa tecnica, modifica il codice di questo esempio per provare a fare una nuova
scheda per la classe JitterBug.

NOTA: Ogni scheda si presenta come file .pde separato all'interno della cartella dello sketch.
Robot 7: Oggetti
Un software oggetto combina metodi (funzioni) e campi (variabili) in un'unit. La classe Robot in
questo esempio definisce tutti gli oggetti robot che verranno creati da essa. Ogni oggetto Robot ha
la propria serie di campi per memorizzare una posizione e la figura che verr disegnata sullo
schermo. Ognuno ha dei metodi per aggiornare la posizione e visualizzare la figura.

I parametri per bot1 e bot2 in setup( ) definiscono le coordinate x e y ed il file .svg che verr usato
per rappresentare il robot. I parametri tempX e tempY vengono esaminati dal constructor e assegnati
ai campi xpos e ypos. Il parametro svgName viene utilizzato per caricare la relativa immagine.
Gli oggetti (bot1 e bot2) disegnano ognuno nella propria posizione e con una figura differente
perch ognuno possiede dei valori unici analizzate dai constructor:

Robot bot1;
Robot bot2;
void setup() {
size(720, 480);
bot1 = new Robot("robot1.svg", 90, 80);
bot2 = new Robot("robot2.svg", 440, 30);
smooth();
}
void draw() {
background(204);
// Aggiorna e visualizza il primo robot
bot1.update();
bot1.display();
// Aggiorna e visualizza il secondo robot
bot2.update();
bot2.display();
}
class Robot {
float xpos;
float ypos;
float angle;
PShape botShape;
float yoffset = 0.0;
// Imposta i valori iniziali nel constructor
Robot(String svgName, float tempX, float tempY) {
botShape = loadShape(svgName);
xpos = tempX;
ypos = tempY;
angle = random(0, TWO_PI);
}
// Aggiorna i campi
void update() {
angle += 0.05;
yoffset = sin(angle) * 20;
}
// Disegna il robot sullo schermo
void display() {
shape(botShape, xpos, ypos + yoffset);
}
}
10/ Array
Abbiamo introdotto nuove idee riguardo la programmazione in
ogni capitolo (variabili, funzioni, oggetti) ed ora arriviamo
all'ultimo passaggio gli array! Un array una lista di variabili
che condividono un nome comune. Gli array sono utili perch
rendono possibile lavorare con molte variabili senza bisogno di
creare un nuovo nome per ciascuna di esse. Questo rende il codice
pi breve, facile da leggere, e pi comodo da aggiornare.

Esempio 10-1: Molte Variabili


Per capire quello che vogliamo dire, facciamo riferimento all' Esempio 7-3. Questo codice funziona
bene se ci stiamo muovendo con solamente una forma, ma cosa succede se vogliamo averne 2?
Abbiamo bisogno di creare una nuova variabile x ed aggiornarla nel draw( ):

float x1 = -20;
float x2 = 20;
void setup() {
size(240, 120);
smooth();
noStroke();
}
void draw() {
background(0);
x1 += 0.5;
x2 += 0.5;
arc(x1, 30, 40, 40, 0.52, 5.76);
arc(x2, 90, 40, 40, 0.52, 5.76);
}

Esempio 10-2: Troppe Variabili


Il codice dell'esempio precedente ancora maneggevole, ma cosa succede se vogliamo avere cinque
cerchi? Abbiamo bisogno di aggiungere ancora tre variabili alle due che gi avevamo:

float x1 = -10;
float x2 = 10;
float x3 = 35;
float x4 = 18;
float x5 = 30;
void setup() {
size(240, 120);
smooth();
noStroke();
}
void draw() {
background(0);
x1 += 0.5;
x2 += 0.5;
x3 += 0.5;
x4 += 0.5;
x5 += 0.5;
arc(x1, 20, 20, 20, 0.52, 5.76);
arc(x2, 40, 20, 20, 0.52, 5.76);
arc(x3, 60, 20, 20, 0.52, 5.76);
arc(x4, 80, 20, 20, 0.52, 5.76);
arc(x5, 100, 20, 20, 0.52, 5.76);
}

Il codice comincia ad essere fuori controllo.

Esempio 10-3: Array, non Variabili


Immagina cosa potrebbe succedere se volessi avere 3,000 cerchi. Questo vorrebbe dire creare 3,000
singole variabili, poi aggiornarne ognuna separatamente. Potresti tenere sotto controllo cos tante
variabili? Davvero vorresti? Usiamo invece un array:

float[] x = new float[3000];


void setup() {
size(240, 120);
smooth();
noStroke();
fill(255, 200);
for (int i = 0; i < x.length; i++) {
x[i] = random(-1000, 200);
}
}
void draw() {
background(0);
for (int i = 0; i < x.length; i++) {
x[i] += 0.5;
float y = i * 0.4;
arc(x[i], y, 12, 12, 0.52, 5.76);
}
}

Spenderemo il resto di questo capitolo parlando dei dettagli che rendono possibile questo esempio.

Creare un Array
Ogni voce dell'array chiamato elemento, ed ognuno ha un valore di indice (index) per
contrassegnare la sua posizione all'interno dell'array. Proprio come le coordinate sullo schermo, i
valori di indice per un array partono il conteggio da 0. Per esempio, il primo elemento in un array
ha il valore di index a 0, il secondo elemento ha il valore di index a 1, e cos via. Se ci sono 20
valori nell'array, il valore di index dell'ultimo elemento sar 19. La Figura 10-1 mostra la struttura
concettuale di un array.

Usare gli array somiglia al lavorare con le singole variabili; segue lo stesso schema. Come sai, puoi
creare una singola variabile con un numero intero chiamata x con questo codice:

int x;

Per creare un array, devi solo aggiungere delle parentesi dopo il tipo di dati:

int[] x;

Il bello di creare un array l'abilit di fare 2, 10, o 100.000 valori di variabile solamente con una
linea di codice. Ad esempio, la riga seguente crea un array di 2.000 variabili intere:

int[] x = new int[2000];

Puoi creare array con tutti i generi di dati di Processing: boolean, float, string, PShape, e cos via,
cos come qualsiasi classe definita dall'utente. Per esempio, il codice seguente crea un array di 32
variabili PImage:

PImage[] images = new PImage[32];

Per creare un array inizia con il nome del tipo di dati, seguito dalle parentesi. Il nome che hai
selezionato per l'array va subito dopo, seguito dall'operatore di assegnazione (il simbolo uguale),
seguito dalla parola chiave new, seguito ancora dal nome del tipo di dati, con il numero di elementi
da creare all'interno delle parentesi. Questo schema funziona per gli array di qualunque tipologia di
dati.

NOTA: Ogni array pu memorizzare solamente un tipo di dati (boolean, int, float, PImage, etc.).
Non puoi mischiare e combinare generi di dati diversi all'interno di un singolo array. Se invece hai
bisogno di farlo, lavora con gli oggetti.

Prima di andare ancora avanti, rallentiamo un poco e parliamo di come lavorare con gli array in
maggior dettaglio. Cos come quando si crea un oggetto, ci sono tre passaggi per lavorare con un
array:

1. Dichiara l'array e definisci il tipo di dati.


2. Crea un array con la parola chiave new e definiscine la lunghezza.
3. Assegna i valori a ciascun elemento.

Ogni passaggio pu verificarsi nella sua riga, oppure tutte le fasi possono essere compresse insieme.
Ciascuno dei tre esempi seguenti mostra una tecnica differente per creare un array chiamato x che
incorpora due interi, 12 e 2. Presta la massima attenzione a quello che accade prima di setup( ) e a
quello che accade all'interno di setup( ).

Esempio 10-4: Dichiarare ed Assegnare un Array


Prima di tutto dichiareremo l'array all'esterno del setup( ) e poi creeremo ed assegneremo i valori
all'interno. La sintassi x[0] si riferisce al primo elemento nell'array e x[1] il secondo:

int[] x; // Declare the array


void setup() {
size(200, 200);
x = new int[2]; // Create the array
x[0] = 12; // Assign the first value
x[1] = 2; // Assign the second value
}

Esempio 10-5: Unire le Assegnazioni di un Array


Questo un esempio leggermente pi compatto, in cui l'array sia dichiarato che creato nella stessa
riga, poi i valori sono assegnati in setup( ):

int[] x = new int[2]; // Dichiara e crea l'array


void setup() {
size(200, 200);
x[0] = 12; // Assegna il primo valore
x[1] = 2; // Assegna il secondo valore
}

Esempio 10-6: Assegnare ad un Array in un Colpo Solo


Puoi anche assegnare i valori all'array quando viene creato, se mettiamo tutto in un'unica istruzione:

int[] x = { 12, 2 }; // Dichiara, crea ed assegna


void setup() {
size(200, 200);
}

NOTA: Evita di creare gli array all'interno di draw( ), poich creare un nuovo array ad ogni frame
rallenter la frequenza dei fotogrammi.

Esempio 10-7: Rivisitare il Primo Esempio

Per fare un esempio completo di come utilizzare gli array, abbiamo ricodificato qui l'Esempio 10-1.
Sebbene non abbiamo ancora visto i pieni benefici rivelati nell'Esempio 10-3, vediamo alcuni
importanti dettagli di come gli array funzionano:

float[] x = {-20, 20};


void setup() {
size(240, 120);
smooth();
noStroke();
}
void draw() {
background(0);
x[0] += 0.5; // Incrementa il primo elemento
x[1] += 0.5; // Incrementa il secondo elemento
arc(x[0], 30, 40, 40, 0.52, 5.76);
arc(x[1], 90, 40, 40, 0.52, 5.76);
}

Ripetizione ed Array
Il ciclo for, introdotto in Ripetizione nel Capitolo 4, facilita il lavoro con array molto ampi
mantenendo sintetico il codice. L'idea di costruire un ciclo che permette di muoversi attraverso
ogni elemento dell'array. Per fare questo, hai bisogno di conoscere la lunghezza dell'array. Il campo
lenght associato ad ogni array memorizza il numero degli elementi. Noi usiamo il nome dell'array
con il punto per avere accesso a questo valore. Facciamo un esempio:

int[] x = new int[2]; // Dichiara e crea l'array


println(x.length); // Stampa 2 sulla console
int[] y = new int[1972]; // Dichiara e crea l'array
println(y.length); // Stampa 1972 sulla console

Esempio 10-8: Inserire un Array in un Ciclo for


Un ciclo for pu essere usato per riempire un array con dei valori, o per leggere i valori che esso
produce. In questo esempio, l'array prima riempito con numeri casuali all'interno del setup( ), poi
questi numeri sono usati per impostare il valore del contorno in draw( ). Ogni volta che il
programma viene eseguito, una nuova serie di numeri casuali inserito nell'array:
float[] gray;
void setup() {
size(240, 120);
gray = new float[width];
for (int i = 0; i < gray.length; i++) {
gray[i] = random(0, 255);
}
}
void draw() {
for (int i = 0; i < gray.length; i++) {
stroke(gray[i]);
line(i, 0, i, height);
}
}

Esempio 10-9: Prendere Traccia dei Movimenti del Mouse


In questo esempio, ci sono due array per immagazzinare la posizione del mouse uno per la
coordinata-x ed uno per la coordinata-y. Questi array memorizzano la posizione del mouse nei 60
fotogrammi precedenti. Ad ogni nuovo frame, i valori delle coordinate x ed y pi vecchi vengono
rimossi e rimpiazzati con i valori attuali di mouseX e mouseY. I nuovi valori sono aggiunti alla
prima posizione dell'array, ma prima che questo accada, ogni valore nell'array spostato di una
posizione verso destra (da dietro in avanti ) per fare spazio ai nuovi numeri. Questo esempio rende
visibile l'azione.

Invece, ad ogni frame, tutte e 60 le coordinate vengono usate per disegnare una serie di ellissi sullo
schermo:

int num = 60;


int x[] = new int[num];
int y[] = new int[num];
void setup() {
size(240, 120);
smooth();
noStroke();
}
void draw() {
background(0);
// Copia i valori dell'array da dietro in avanti
for (int i = x.length-1; i > 0; i--) {
x[i] = x[i-1];
y[i] = y[i-1];
}
x[0] = mouseX; // Imposta il primo elemento
y[0] = mouseY; // Imposta il primo elemento
for (int i = 0; i < x.length; i++) {
fill(i * 4);
ellipse(x[i], y[i], 40, 40);
}
}

NOTA: La tecnica di immagazzinare una memoria mobile di numeri in un array come mostrato in
questo esempio e nella Figura 10-2 meno efficiente di una tecnica alternativa che utilizza
l'operatore % (modulo). Questo spiegato nell'esempio Examples Basics Input
StoringInput che incluso con Processing.

Array di Oggetti
I due brevi esempi in questa sezione raccolgono insieme ogni principale concetto di
programmazione contenuto in questo libro: variabili, iterazione, condizionali, funzioni, oggetti ed
array. Costruire un array di oggetti pi o meno la stessa cosa di costruire un array come lo
abbiamo spiegato nelle pagine precedenti, ma con una considerazione in pi: poich ogni elemento
dell'array un oggetto, dev'essere prima creato con la parola chiave new (come ogni altro oggetto)
prima che sia assegnato ad un array. Con una classe personalizzata come JitterBug (vedi il Capitolo
9), questo significa usare new per impostare ogni elemento prima che sia assegnato all'array.
Oppure, per una classe precostruita di Processing come PImage, significa utilizzare la funzione
loadImage( ) per creare un oggetto prima che sia assegnato.

Esempio 10-10: Gestire Molti Oggetti


Questo esempio crea un array di 33 oggetti JitterBug e poi aggiorna e ne visualizza ognuno in
draw( ). Per far funzionare questo esempio, hai bisogno di aggiungere la classe JitterBug al codice:

JitterBug[] bugs = new JitterBug[33];


void setup() {
size(240, 120);
smooth();
for (int i = 0; i < bugs.length; i++) {
float x = random(width);
float y = random(height);
int r = i + 2;
bugs[i] = new JitterBug(x, y, r);
}
}
void draw() {
for (int i = 0; i < bugs.length; i++) {
bugs[i].move();
bugs[i].display();
}
}
// Copia qui la classe JitterBug

L'array dell'esempio finale carica una sequenza di immagini e ne memorizza ognuno come una
elemento all'interno di un array di oggetti PImage.
Esempio10-11: Sequenze di Immagini
Per eseguire questo esempio, acquisisci le immagini dal file media.zip come descritto nel
Capitolo 6. Le immagini sono nominate in sequenza (frame-0001.png, frame-0002.png, e cos via),
che rende possibile creare il nome di ciascun file in un ciclo for, come vediamo nell'ottava linea del
programma:

int numFrames = 12; // Il numero dei frame


PImage[] images = new PImage[numFrames]; // Crea un array
int currentFrame = 1;
void setup() {
size(240, 120);
for (int i = 1; i < images.length; i++) {
String imageName = "frame-" + nf(i, 4) + ".png";
images[i] = loadImage(imageName); // Carica ogni immagine
}
frameRate(24);
}
void draw() {
image(images[currentFrame], 0, 0);
currentFrame++; // Prossimo frame
if (currentFrame >= images.length) {
currentFrame = 1; // Ritorna al primo frame
}
}

La funzione nf( ) formatta i numeri cosicch nf (1,4) restituisce la stringa 0001 e nf (11,4)
restituisce 0011. Questi valori vengono concatenati con l'inizio del nome del file (frame-) e con
la fine (.png) per creare il nome completo del file come una variabile String. I file sono caricati
nell'array della riga successiva. Le immagini vengono visualizzate sullo schermo una alla volta in
draw( ). Quando l'ultima immagine nell'array viene visualizzata, il programma torna all'inizio
dell'array e mostra di nuovo le immagini in sequenza.
Robot 8: Array
Gli array facilitano ad un programma il lavoro con pi elementi. In questo esempio, un array di
oggetti Robot viene dichiarato all'inizio. L'array poi collocato all'interno di setup( ), ed ogni
oggetto Robot viene creato all'interno del ciclo for. Nel draw( ), un altro ciclo for usato per
aggiornare e visualizzare ogni elemento dell'array dei robot.

Il ciclo for ed un array creano una potente combinazione. Nota le sottili differenze tra il codice in
questo esempio e Robot 7 (vedi Robot 7: Oggetti nel Capitolo 9 ) in contrasto con gli estremi
cambiamenti nel risultato visivo. Una volta che un array viene creato ed un ciclo for messo in atto,
diventa facile lavorare con 3 elementi cos come con 3000.

La decisione di caricare il file SVG all'interno del setup( ) invece che nella classe Robot la
modifica maggiore da Robot 7. Questa scelta stata effettuata cos che il file venga caricato una
sola volta, invece che tante volte quanti sono gli elementi nell'array (in questo caso, 20 volte).
Questo cambiamento fa si che il codice parta prima poich caricare un file richiede tempo, ed
inoltre usa meno memoria poich il file memorizzato solo una volta. Ogni elemento dell'array bot
fa riferimento allo stesso file.

Robot[] bots; // Dichiara l'array di oggetti robot


void setup() {
size(720, 480);
PShape robotShape = loadShape("robot1.svg");
// Crea l'array di oggetti robot
bots = new Robot[20];
// Crea ciascun oggetto
for (int i = 0; i < bots.length; i++) {
// Create a random x-coordinate
float x = random(-40, width-40);
// Assegna la coordinata y in base all'ordine
float y = map(i, 0, bots.length, -100, height-200);
bots[i] = new Robot(robotShape, x, y);
}
smooth();
}
void draw() {
background(204);
// Aggiorna e visualizza ogni robot nell'array
for (int i = 0; i < bots.length; i++) {
bots[i].update();
bots[i].display();
}
}
class Robot {
float xpos;
float ypos;
float angle;
PShape botShape;
float yoffset = 0.0;
// Imposta il valore iniziale nel constructor
Robot(PShape shape, float tempX, float tempY) {
botShape = shape;
xpos = tempX;
ypos = tempY;
angle = random(0, TWO_PI);
}
// Aggiorna i campi
void update() {
angle += 0.05;
yoffset = sin(angle) * 20;
}
// Disegna il robot sullo schermo
void display() {
shape(botShape, xpos, ypos + yoffset);
}
}
11/ Estendere
Questo libro si concentra nell'utilizzare Processing per grafiche
interattive, poich questo il cuore di ci a cui Processing tende.
D'altronde, il software pu fare molto di pi ed spesso parte di
progetti che si muovono al di l di un semplice schermo del
computer. Ad esempio, Processing stato usato per controllare
macchine, esportare immagini per film ad alta definizione, ed
esportare modelli per stampe 3D.
Durante l'ultima decade, Processing stato utilizzato per fare video musicali per Radiohead e
R.E.M., per creare illustrazioni per pubblicazioni come Nature ed il New York Times, per produrre
sculture per mostre, per controllare una parete video di 120 per 120 piedi, per cucire maglioni, e
molto altro. Processing deve questa flessibilit al suo sistema di librerie.

Una libreria di Processing una collezione di codice che estende il software al di l delle sue
funzioni e classi fondamentali. Le librerie hanno avuto un'importanza fondamentale per la crescita
del progetto, poich lasciano aggiungere agli sviluppatori nuove funzionalit velocemente. Come
piccoli progetti autosufficienti, le librerie sono pi semplici da gestire di quanto lo sarebbero queste
funzioni se fossero integrate nel software principale.

In aggiunta alle librerie incluse in Processing (che sono chiamate core libraries), ci sono oltre 100
contributed libraries che si possono raggiungere tramite un link dal sito web di Processing. Tutte le
librerie sono elencate online a http://processing.org/reference/libraries/.

Per usare una libreria, seleziona Import Library dal menu Sketch. Scegliere una libreria aggiunger
una riga di codice che indica che la libreria sar usata con lo sketch corrente. Ad esempio, quando la
libreria OpenGL viene aggiunta, appare questa riga di codice in cima allo sketch:

import processing.opengl.*;

Prima che una libreria possa essere importata attraverso il menu Sketch, dev'essere scaricata dal suo
sito web e posizionata all'interno della cartella libraries nel tuo computer. La tua cartella libraries
collocata nel tuo sketchbook. Puoi trovare la posizione del tuo sketchbook aprendo le Preferences.
Posiziona la libreria scaricata in una cartella nel tuo sketchbook chiamata libraries. Se questa
cartella ancora non esiste, creala.

Come gi menzionato, ci sono pi di 100 librerie di Processing, cos non possono venir tutte
discusse qui in modo esaustivo.
3D
Ci sono due modi di disegnare in 3D con Processing: entrambi richiedono di aggiungere un terzo
parametro alla funzione size( ) per cambiare il modo in cui la grafica viene disegnata. Di default,
Processing disegna usando un rendering 2D molto preciso, ma lento. Questo il renderer JAVA2D.
Una versione qualche volta pi veloce ma di qualit pi bassa il P2D, il renderer 2D di
Processing. Puoi anche cambiare il renderer in Processing 3D, chiamato P3D, oppure OpenGL, per
permettere ai tuoi programmi di disegnare in una dimensione in pi, l'asse z (vedi la Figura 11-1).

Render con Processing 3D in questo modo:

size(800,600, P3D);

Ed OpenGL in questo modo:

size (800, 600, OPENGL) ;

Il renderer P3D incorporato, invece il renderer OpenGL una libreria e richiede l'istruzione
import all'interno del codice, come mostrato all'inizio dell'Esempio 11-1. Il renderer OpenGL fa uso
di grafica pi veloce che disponibile sulla maggior parte delle macchine vendute al giorno d'oggi.

NOTA: Il renderer OpenGL non garantisce la velocit in ogni occasione; vedi le referenze per
size( ) per maggiori dettagli.

Molte delle funzioni introdotte in questo libro hanno variazioni per lavorare in 3D. Ad esempio, le
funzioni base di disegno point( ), line( ), e vertex( ) semplicemente aggiungono i parametri z ai
parametri x ed y che sono stati spiegati in precedenza. Anche le trasformazioni translate( ), rotate( )
e scale( ) funzionano in 3D.

Esempio 11-1: Una Demo 3D


Molte funzioni 3D sono spiegate nelle Referenze di Processing, ma qui c' un esempio per farti
iniziare:

import processing.opengl.*;
void setup() {
size(440, 220, OPENGL);
noStroke();
fill(255, 190);
}
void draw() {
background(0);
translate(width/2, height/2, 0);
rotateX(mouseX / 200.0);
rotateY(mouseY / 100.0);
int dim = 18;
for (int i = -height/2; i < height/2; i += dim*1.2) {
for (int j = -height/2; j < height/2; j += dim*1.2) {
beginShape();
vertex(i, j, 0);
vertex(i+dim, j, 0);
vertex(i+dim, j+dim, -dim);
vertex(i, j+dim, -dim);
endShape();
}
}
}

Quando inizi a lavorare con il 3D, possibile esplorare nuove funzioni. possibile cambiare la
visuale, le luci, le propriet dei materiali, e disegnare forme 3D come sfere e cubi.

Esempio 11-2: Illuminazione


Questo esempio costruito sull'Esempio 11-1 sostituendo i rettangoli con i cubi e aggiungendo
alcuni tipi di luci. Prova a commentare ed a decommentare luci differenti per vedere come ciascuna
lavori da sola ed in combinazione con le altre:

import processing.opengl.*;
void setup() {
size(420, 220, OPENGL);
noStroke();
fill(255);
}
void draw() {
lights();
//ambientLight(102, 102, 102);
//directionalLight(255, 255, 255, // Color
// -1, 0, 0); // Direction XYZ
//pointLight(255, 255, 255, // Color
// mouseX, 110, 50); // Position
//spotLight(255, 255, 255, // Color
// mouseX, 0, 200, // Position
// 0, 0, -1, // Direction XYZ
// PI, 2); // Concentration
rotateY(PI/24);
background(0);
translate(width/2, height/2, -20);
int dim = 18;
for (int i = -height/2; i < height/2; i += dim*1.4) {
for (int j = -height/2; j < height/2; j += dim*1.4) {
pushMatrix();
translate(i, j, -j);
box(dim, dim, dim);
popMatrix();
}
}
}

Ci sono quattro tipi di luci in Processing: spot, a punto, direzionali, e ambientali. Le luci spot si
irradiano in una forma conica; hanno una direzione, una collocazione ed un colore. Le luci a punto
si irradiano da un singolo punto come una lampadina di qualsiasi colore. Le luci direzionali si
proiettano in una direzione per creare forti luci ed ombre. Le luci ambientali creano una luce
uniforme di qualsiasi colore sull'intera scena e vengono per lo pi utilizzate con le altre luci.
La funzione lights( ) crea un'impostazione di luci predefinita con una luce ambientale ed una
direzionale. Le luci devono essere resettate ogni volta all'interno di draw( ), quindi dovrebbero
comparire all'inizio di draw( ) per assicurare risultati consistenti.

Lavorare in 3D introduce l'idea di una camera puntata sulla scena tridimensionale che stata
costruita. Come una videocamera reale, mappa lo spazio 3D nel piatto piano 2D dello schermo.
Muovere la camera cambia il modo in cui Processing mappa le coordinate 3D del tuo disegno nello
schermo 2D.

Esempio 11-3: La Telecamera di Processing


Di default, Processing crea una telecamera che punta al centro dello schermo, quindi le forme
lontano dal centro sono viste in prospettiva. La funzione camera( ) offre un controllo sulla
posizione della videocamera, la posizione in cui puntata, e l'orientamento (sopra, sotto, inclinato).
Nell'esempio seguente, il mouse viene usato per muovere la posizione in cui la telecamera
puntata:

import processing.opengl.*;
void setup() {
size(420, 220, OPENGL);
noStroke();
}
void draw() {
lights();
background(0);
float camZ = (height/2.0) / tan(PI*60.0 / 360.0);
camera(mouseX, mouseY, camZ, // Posizione della telecamera
width/2.0, height/2.0, 0, // Bersaglio della telecamera
0, 1, 0); // Orientamento della telecamera
translate(width/2, height/2, -20);
int dim = 18;
for (int i = -height/2; i < height/2; i += dim*1.4) {
for (int j = -height/2; j < height/2; j += dim*1.4) {
pushMatrix();
translate(i, j, -j);
box(dim, dim, dim);
popMatrix();
}
}
}

Questa sezione ha presentato la punta dell'iceberg delle capacit del 3D. In aggiunta alle
funzionalit di base menzionate qui, ci sono molte altre librerie di Processing che aiutano a generare
forme 3D, a caricare ed esportare le forme, e forniscono un controllo pi avanzato della telecamera.

Esportazione delle Immagini


Le immagini animate create da un programma di Processing possono essere trasformate in una
sequenza di file con la funzione saveFrame( ). Quando saveFrame( ) si trova alla fine del draw( ),
memorizza una sequenza numerata di immagini in formato TIFF dell'output del programma nella
cartella sketch, nominandoli screen-0001.tif, screen-0002.tif, e cos via. Questi file possono essere
importati in un programma di video o animazione e salvati come un filmato. Puoi anche specificare
il nome del file ed il formato dell'immagine con una riga di codice come questa:

saveFrame (output-####.png);

NOTA: Quando utilizzi saveFrame( ) all'interno del draw( ), un nuovo file viene salvato ad ogni
frame quindi stai attento poich pu rapidamente riempire la tua cartella dello sketch con migliaia
di file.
Usa il simbolo # (cancelletto) per mostrare dove i numeri vengono mostrati all'interno del nome del
file. Questi vengono rimpiazzati con il numero attuale dei frame quando il file viene salvato. Puoi
anche specificare una sottocartella dove salvare le immagini, la quale utile quando si lavora con
molti fotogrammi:

saveFrame (frames/output-####.png);

Esempio 11-4: Salvare le immagini


Questo esempio mostra come salvare le immagini memorizzando abbastanza fotogrammi di
un'animazione di due secondi. Il programma viene eseguito a 30 frame al secondo e si conclude
dopo 60 frame:

float x = 0;

void setup() {
size(720, 480);
smooth();
noFill();
strokeCap(SQUARE);
frameRate(30);
}
void draw() {
background(204);
translate(x, 0);
for (int y = 40; y < 280; y += 20) {
line(-260, y, 0, y + 200);
line(0, y + 200, 260, y);
}
if (frameCount < 60) {
saveFrame("frames/SaveExample-####.tif");
} else {
exit();
}
x += 2.5;
}

Processing scriver un'immagine basata sull'estensione del file che hai usato (.png, .jpg, o .tif sono
tutti incorporati, ed alcune piattaforme possono supportarne altre). Un'immagine .tif viene salvata
senza compressione, il quale un metodo pi veloce ma che richiede uno spazio maggiore nel
disco. Sia il .png che il .jpg creeranno file pi piccoli, ma a causa della compressione, verr
solitamente richiesto pi tempo per salvarlo, rendendo l'esecuzione del file pi lenta.

Se ci che devi produrre grafica vettoriale, puoi scriverlo in file PDF per una maggiore
risoluzione. La libreria PDF Export rende possibile scrivere file PDF direttamente dallo sketch.
Questi file di grafica vettoriale possono essere ridimensionati ad ogni dimensione senza perdere
risoluzione, il che li rende ideale per una prodotto da stampare dai poster alle insegne ad interi
libri.

Esempio 11-5: Disegnare in formato PDF


Questo esempio viene costruito sull'Esempio 11-4 per disegnare pi parentesi uncinate di differenti
misure, ma il movimento viene rimosso. Viene creato un file PDF chiamato Ex-11-5.pdf per il terzo
ed il quarto parametro di size( ):

import processing.pdf.*;
void setup() {
size(600, 800, PDF, "Ex-11-5.pdf");
noFill();
strokeCap(SQUARE);
}
void draw() {
background(255);
for (int y = 100; y < height - 300; y+=20) {
float r = random(0, 102);
strokeWeight(r / 10);
beginShape();
vertex(100, y);
vertex(width/2, y + 200);
vertex(width-100, y);
endShape();
}
exit();
}

La geometria non viene disegnata sullo schermo; scritta direttamente nel file PDF, il quale
salvato nella cartella sketch. Il codice in questo esempio viene eseguito una volta e poi si conclude
alla fine del draw( ). Il prodotto risultante mostrato nella Figura 11-2.

Ci sono altri esempi di PDF Export inclusi nel software di Processing. Guarda nella sezione PDF
Export degli esempi di Processing per vedere altre tecniche.

Hello Arduino
Arduino una piattaforma per prototipi elettronici con una serie di schede di microcontroller ed il
software per programmarle. Processing e Arduino condividono una lunga storia insieme; sono dei
progetti fratelli con molte idee ed obiettivi simili, sebbene possiedano campi separati.
Poich condividono lo stesso editor ed ambiente di programmazione ed una sintassi simile, facile
muoversi tra di loro e trasferire conoscenza dall'uno all'altro.

In questa sezione, ci focalizziamo con sulla lettura di dati da Processing ad una scheda Arduino e
poi sul visualizzare questi dati sullo schermo. Ci rende possibile l'utilizzo di nuovi input in un
programma di Processing e permette ai programmatori di Arduino di vedere i propri sensori di
ingresso come grafica. Questi nuovi input possono essere i pi disparati che possono venir collegati
ad una scheda Arduino. Questi dispositivi spaziano da un sensore di distanza ad una bussola ad un
network mesh a dei sensori di temperatura.

Questa sezione da per scontato che tu possieda una scheda Arduino e che possiedi gi una
conoscenza di base per saperlo usare. Se non cos, puoi saperne di pi online a
http://www.arduino.cc e nell'ottimo libro Getting Started With Arduino di Massimo Banzi
(O'Reilly). Una volta che hai compreso le basi, puoi imparare altro sull'invio di dati da Processing
ad Arduino in un altro eccezionale libro, Making Things Talk di Tom Igoe (O'Reilly).

I dati possono essere trasferiti dagli sketch di Processing ad una scheda Arduino con un po' d'aiuto
dalla Serial Library di Processing. Serial un formato i dati che spedisce un byte alla volta. Nel
mondo di Arduino, un byte una tipologia di dati che pu immagazzinare i valori tra lo 0 ed il 255;
lavora come un int, ma con un intervallo pi breve. I numeri pi grandi sono inviati per essere
frammentati in una lista di byte e poi riassemblati successivamente.

Nell'esempio successivo, ci concentriamo sulla parte riguardante Processing e lasciamo il codice di


Arduino semplificato. Visualizziamo i dati in arrivo dalla scheda Arduino un byte alla volta. Con le
tecniche apprese in questo libro e i centinaia di esempi online di Arduino, speriamo che sia
abbastanza per farti iniziare.

Esempio 11-6: Leggere un sensore


Il seguente codice di Arduino viene usato con i prossimi tre esempi di Processing:

// Nota:Questo un codice per la scheda Arduino, non per Processing

int sensorPin = 0; // Seleziona pin di input


int val = 0;
void setup() {
Serial.begin(9600); // Apri porta seriale
}
void loop() {
val = analogRead(sensorPin) / 4; // Leggi i valori dal sensore
Serial.print(val, BYTE); // Stampa la variabile nella porta seriale
delay(100); // Aspetta 100 millisecondi
}

Ci sono due dettagli importanti da notare riguardo questo esempio di Arduino. Primo, richiede di
inserire un sensore nell'ingresso analogico sul pin 0 nella scheda Arduino.
Potresti usare un sensore luminoso ( chiamato anche foto-resistenza, fotocellula, o resistenza
dipendente dalla luce) oppure un'altra resistenza analogica come un termistore (resistenza sensibile
alla temperatura), un sensore di flessione, od un sensore di pressione (resistenze sensibili alla forza).
Il diagramma ed il disegno dei circuiti della breadboard con i componenti mostrata nella Figura
11-4. Poi nota che il valore riportato dalla funzione analogRead( ) si trova tra lo 0 e 1023, cos lo
dividiamo per 4 per convertirlo ad un intervallo tra 0 e 255 cos che i dati possono essere inviati in
un singolo byte.

Esempio 11-7: Leggere i Dati dalla Porta Seriale


Il primo esempio di visualizzazione mostra come leggere i dati seriali dalla scheda Arduino e come
convertire questi dati nei valori che si adattano alle dimensioni dello schermo:

import processing.serial.*;
Serial port; // Crea un oggetto dalla classe Serial
float val; // I dati ricevuti dalla porta seriale
void setup() {
size(440, 220);
// NOTA IMPORTANTE:
// La prima porta seriale estratta da Serial.list()
// dev'essere il tuo Arduino. Se non cos, decommenta la linea
// di testo cancellando le // prima di essa. Esegui lo sketch
// un'altra volta per vedere una lista di porte seriali. Poi
// cambia lo 0 all'interno di [ e ] con il numero della porta
// a cui il tuo Arduino connesso
//println(Serial.list());
String arduinoPort = Serial.list()[0];
port = new Serial(this, arduinoPort, 9600);
}
void draw() {
if (port.available() > 0) { // Se i dati non sono disponibili,
val = port.read(); // leggilo e memorizzalo in val
val = map(val, 0, 255, 0, height); // converti il valore
}
rect(40, val-10, 360, 20);

La libreria Serial viene importata nella prima linea e la porta seriale viene aperta in setup( ).
Questo pu o non pu essere facile per far si che lo sketch di Processing con la scheda Arduino;
dipende dalla tua configurazione hardware. C' spesso pi di un dispositivo con cui lo sketch di
Processing pu comunicare. Se il codice non funziona la prima volta, leggi attentamente il
commento in setup( ) e segui le istruzioni.

All'interno del draw( ), il valore viene portato all'interno del programma con il metodo read( )
dell'oggetto Serial. Il programma legge i dati dalla porta seriale solamente quando disponibile un
nuovo byte. Il metodo available( ) prova a vedere se un nuovo byte pronto e restituisce il numero
dei byte disponibili. Questo programma viene scritto cos che un singolo nuovo byte verr letto ogni
volta all'interno di draw( ). La funzione map( ) converte il valore in arrivo dal suo range iniziale che
va da 0 a 255 ad un range che va da 0 all'altezza dello schermo;
In questo programma, da 0 a 220.

Esempio 11-8: Visualizzare il Flusso di Dati


Ora che i dati sono riusciti a passare, li visualizzeremo in un formato pi interessante. I valori che
entrano direttamente da un sensore sono spesso incostanti, ed utile semplificarli facendone una
media. Qui presenteremo il segnale grezzo proveniente da un sensore di luce illustrato nella figura
11-4 nella met superiore dell'esempio ed il segnale perfezionato nella met inferiore:

import processing.serial.*;
Serial port; // Crea un oggetto dalla classe Serial
float val; // I dati ricevuti dall porta seriale
int x;
float easing = 0.05;
float easedVal;
void setup() {
size(440, 440);
frameRate(30);
smooth();
String arduinoPort = Serial.list()[0];
port = new Serial(this, arduinoPort, 9600);
background(0);
}
void draw() {
if ( port.available() > 0) { // Se i dati sono disponibili,
val = port.read(); // leggili e memorizzali in val
val = map(val, 0, 255, 0, height); // Converti i valori
}
float targetVal = val;
easedVal += (targetVal - easedVal) * easing;
stroke(0);
line(x, 0, x, height); // Linea nera
stroke(255);
line(x+1, 0, x+1, height); // Linea bianca
line(x, 220, x, val); // Valore grezzo
line(x, 440, x, easedVal + 220); // Valore medio
x++;
if (x > width) {
x = 0;
}
}

Simile all'Esempio 5-8 e 5-9, questo sketch usa la tecnica easing.


Ogni nuovo byte dalla scheda Arduino impostato come il valore obiettivo, la differenza fra il
valore corrente ed il valore obiettivo viene calcolata, ed il valore corrente si muove pi vicino
all'obiettivo. Regola la variabile easing per influenzare l'intensit dello smoothing applicata al
valore in arrivo.

Esempio 11-9: Un altro modo di guardare ai Dati


Questo esempio ispirato dagli schermi di visualizzazione dei radar. I valori sono letti nello stesso
modo dalla scheda Arduino, ma sono visualizzati in un pattern circolare usando le funzioni di sin( )
e cos( ) introdotte precedentemente negli Esempi che vanno dal 7-12 al 7-15:

La variabile angle viene aggiornata continuamente per muovere la linea disegnando il valore
corrente attorno al cerchio, e la variabile val ridimensiona la lunghezza della linea in movimento,
per impostare la sua distanza dal centro dello schermo.
Dopo un giro attorno al cerchio, i valori iniziano ad essere scritti in cima ai dati precedenti.

Siamo eccitati dalla potenziale di utilizzare Processing e Arduino insieme per collegare il mondo del
software e dell'elettronica. A differenza di come sono fatti gli esempi stampati in questo libro, le
comunicazioni possono essere bidirezionali. Gli elementi sullo schermo possono anche influenzare
ci che accade sulla scheda Arduino. Ci significa che tu puoi usare un programma di Processing
come un'interfaccia tra il tuo computer e motori, altoparlanti, luci, camere, sensori, e praticamente
qualsiasi cosa che pu essere controllata da un segnale elettrico. Di nuovo, ulteriori informazioni
riguardo Arduino possono esser trovate ad http://www.arduino.cc .

Community
Abbiamo lavorato duramente per rendere facile l'esportazione di programmi di Processing cosicch
tu possa condividerli facilmente con altri. Nel secondo capitolo, abbiamo parlato della condivisione
dei tuoi programmi attraverso l'esportazione. Crediamo che la condivisione favorisca
l'apprendimento e lo sviluppo della comunit. Nel momento in cui modificherai i programmi di
questo libro ed inizierai a scrivere i tuoi programmi da zero, ti incoraggiamo a rivedere questa
sezione del libro e condividere il tuo lavoro con altri.
Allo stato attuale, i gruppi di OpenProcessing, Vimeo, Flickr, e la Processing Wiki sono luoghi
eccitanti da visitare e a cui dare un contributo.
Su Twitter, le ricerche di #Processing e Processing.org producono risultati interessanti.
Queste comunit sono sempre in movimento.
Controlla il sito principale di Processing
( http://www.processing.org ) per link recenti come questi:

>> http://www.openprocessing.org
>> http://www.vimeo.com/tag:processing.org
>> http://www.flickr.com/groups/processing/
>> http://www.delicious.com/tag/processing.org/
A/Suggerimenti per Scrivere Codice
Codificare un tipo di scrittura. Come tutti le tipologie di scrittura, il codice ha le sue regole
specifiche. Per fare un confronto, citeremo velocemente alcune delle regole dell'Inglese su cui non
ti sarai soffermato da un po'.
Alcune tra le regole pi invisibili sono lo scrivere da sinistra a destra e l'inserire lo spazio tra ogni
parola. Altre regole evidenti sono le convinzioni ortografiche, mettere le lettere maiuscole all'inizio
dei nomi di persone e luoghi, ed usare la punteggiatura alla fine delle frasi per dare enfasi!
Se non rispettiamo una o pi di queste regole quando scriviamo una mail ad un amico, il messaggio
arriva comunque.
Ad esempio, Ciao ben, cm stai gg? altrettanto chiaro di, Ciao Ben, come stai oggi?
D'altronde la flessibilit con le regole della scrittura non applicabile alla programmazione.
Poich stai scrivendo per comunicare con un computer, invece che con un'altra persona, hai bisogno
di essere pi preciso e attento.
Un carattere fuori posto fa spesso la differenza tra un programma che funziona ed uno che non
funziona.

Processing prova a dirti dov' stato fatto l'errore ed a indovinare qual l'errore.
Quando premi il pulsante Run, se ci sono problemi grammaticali (di sintassi) con il tuo codice (noi
li chiamiamo bugs), l'area dei messaggi diventa rossa e Processing prova ad evidenziare la linea di
codice che si sospetta abbia il problema.
La linea di codice con il bug spesso una riga sotto o sopra quella evidenziata, anche se in alcuni
casi non in nessun posto vicino.
Il testo nell'area dei messaggi cerca di essere utile suggerisce il potenziale problema, ma talvolta il
messaggio troppo criptico da capire.
Per un principiante, questi messaggi di errore possono essere frustranti.
Bisogna capire che Processing un semplice software che prova ad essere d'aiuto, ma ha una
conoscenza limitata di ci che stai provando a fare.

I lunghi messaggi di errore sono stampati pi in dettaglio sulla Console, e qualche volta scorrere il
testo pu offrire un suggerimento.
Inoltre Processing pu trovare pi di un bug alla volta. Se il tuo programma ha pi di un bug, devi
continuare ad eseguire il programma e sistemarli uno alla volta.

Ti preghiamo di leggere e rileggere attentamente i seguenti suggerimenti per aiutarti a scrivere un


codice pulito.

Funzioni e Parametri
I programmi sono composti di tante piccole parti, le quali sono raggruppate insieme per creare
strutture pi grandi. Abbiamo un sistema simile nella lingua Inglese: le parole sono raggruppate in
frasi, le quali sono raggruppate in periodi, i quali sono raggruppati in paragrafi.
L'idea la stessa nel codice, ma le piccole parti hanno nomi differenti e si comportano in modo
differente. Funzioni e Parametri sono due parti importanti. Le funzioni sono i blocchi di
costruzione principali di un programma di Processing. I parametri sono valori che definiscono il
comportamento delle funzioni.
Prendi in considerazione una funzione come background( ). Come suggerisce il nome, usata per
impostare il colore dello sfondo della finestra di visualizzazione. La funzione ha tre parametri che
definiscono il colore. Questi numeri definiscono le componenti di rosso, verde e blu del colore
composto. Ad esempio, il codice seguente disegna uno sfondo blu:

background(51, 102, 153);

Guarda attentamente questa singola riga di codice. I dettagli chiave sono le parentesi dopo il nome
della funzione che racchiudono i numeri, le virgole tra ogni numero, ed il punto e virgola alla fine
della riga. Il punto e virgola usato come un punto. Ci significa che una dichiarazione chiusa ed
il computer pu guardare l'inizio della prossima.
Tutte queste parti devono essere l perch il codice venga eseguito.
Confronta la riga di esempio precedente a queste tre versioni incomplete della stessa riga:

background 51, 102, 153; // Errore! Mancano le parentesi


background(51 102, 153); // Errore! Manca una virgola
background(51, 102, 153) // Errore! Manca un punto e virgola

Il computer spietato riguardo anche la pi piccola omissione o deviazione da quello che si aspetta.
Se tu ricordi queste parti, avrai pochi bug. Ma se ti dimentichi di digitarli, come tutti facciamo, non
un problema. Processing ti avvertir del problema, e quando risolto, il programma verr eseguito
correttamente.

Scrivere Codice a Colori


L'ambiente di Processing produce un codice a colori in differenti parti di ogni programma.
Le parole che sono parte di Processing sono disegnate in blu e arancio per distinguerle dalle parti di
programma che inventi tu stesso. Le parole che vengono usate unicamente per il tuo programma,
come i nomi delle variabili e delle funzioni, sono scritte in nero. I simboli di base come ( ), [ ], e >
sono anch'essi in nero.

Commenti
I commenti sono annotazioni che si scrivono a se stessi (o ad altre persone) all'interno del codice.
Potresti usarli per chiarire cosa fa il codice in linguaggio semplice e per fornire informazioni
addizionali come il titolo e l'autore del programma. Un commento inizia con due slash (//) e
continua fino alla fine della riga:

// Questo un commento ad una linea

Puoi creare un commenti in pi linee facendolo partire con /* e finirlo con */. Ad esempio:

/* Questo commento
continua per pi
di una linea
*/

Quando un commento digitato correttamente, il colore del testo diventer grigio. L'intera area
commentata diventer grigia cos potrai vederne chiaramente l'inizio e la fine.
Maiuscolo e Minuscolo
Processing distingue le lettere maiuscole da quelle minuscole e perci legger Ciao come una
parola distinta da ciao. Se stai tentando di disegnare un rettangolo con la funzione rect( ) e
scriverai Rect( ), il codice non verr eseguito. Puoi vedere se Processing riconosce il colore
intenzionale osservando il colore del testo.

Stile
Processing flessibile riguardo alla quantit di spazio che utilizzi per formattare il tuo codice.
Processing ignora se scrivi:

rect(50, 20, 30, 40);

oppure:

rect (50,20,30,40);

oppure:

rect ( 50,20,
30, 40)

Tuttavia, nel tuo interesse creare codice leggibile. Ci diventa importante specialmente quando il
codice cresce in lunghezza. Una formattazione pulita rende la struttura del codice immediatamente
leggibile, ed una formattazione scomposta spesso nasconde i problemi. Prendi l'abitudine di scrivere
codice pulito. Ci sono differenti modi di formattare il codice in modo corretto, ed il modo che scegli
per spaziare gli oggetti fa parte delle preferenze personali.

Console
La console l'area in fondo all'ambiente di Processing. Puoi scrivere messaggi sulla Console con la
funzione println( ). Ad esempio, il codice seguente stampa un messaggio seguito dall'orario attuale:

println("Hello Processing.");
println("The time is " + hour() + ":" + minute());

La Console essenziale per osservare cosa sta succedendo all'interno del tuo programma mentre
in esecuzione. Viene usato per stampare il valore delle variabili in modo che tu possa prenderne
nota, per confermare se gli eventi stanno accadendo, e per determinare dove il programma sta
avendo un problema.

Un Passo alla Volta


Raccomandiamo di scrivere poche righe di codice alla volta ed eseguire il codice frequentemente
per esser sicuri che i bug non vengano accumulati senza che tu lo sappia. Ogni programma
ambizioso scritto una riga alla volta. Suddividi il tuo progetto in semplici sottoprogetti e
completali uno alla volta cos che potrai avere tanti piccoli successi, invece di uno sciame di bug.
Se hai un bug, prova ad isolare l'area di codice dove pensi sia il problema. Prova a pensare al
riparare i bug come a risolvere un mistero o un puzzle. Se ti ritrovi bloccato o sei frustrato, prenditi
una pausa per chiarire la tua mente e chiedi ad un amico un aiuto. Talvolta la risposta proprio sotto
il tuo naso ma richiede un secondo parere per palesarsi.
B/Tipologie di dati
Ci sono diverse categorie di dati. Ad esempio, pensa ai dati su una carta d'identit. La carta ha
numeri per memorizzare peso, altezza, data di nascita, indirizzo e codice postale. Ci sono parole per
memorizzare un nome di persona e la citt. Ci sono inoltre dati in immagini (una foto) e spesso una
scelta di donare gli organi, una scelta si/no. Ognuno dei tipi seguenti spiegato pi in dettaglio in
altre parti del libro, ma questo un riepilogo:

Nome Descrizione Gamma di valori


int Numeri interi -2,147,483,648 a 2,147,483,647
float Valori decimali Da -3.40282347E+38 a
3.40282347E+38
boolean Valore logico Vero o falso
char Singolo carattere A-z, 0-9 e simboli
String Sequenza di caratteri Qualunque lettera, parola, frase
e cos via
PImage Immagine PNG, JPG o GIF N/A
PFont Font in formato VLW: usa lo N/A
strumento Create Font per
crearlo
PShape File SVG N/A

Come linea guida, un numero decimale ha quattro cifre di precisione dopo il punto decimale.
Se stai contando o facendo brevi misurazioni, dovresti usare un valore int per prendere le misure, e
poi magari reimpostarle in un float quando hai la necessit di utilizzarle.

Ci sono ulteriori tipologie di dati che non vengono menzionate qui, ma queste sono le pi utili per il
lavoro tipico di Processing. Infatti, come menzionato nel capitolo 9, ci sono infiniti tipi di dati,
poich ogni nuova classe un tipo differente di dati.
C/Ordine delle Operazioni
Quando i calcoli matematici sono svolti in un programma, ogni operazione prende posto secondo un
ordine prefissato. Questo ordine delle operazioni assicura che il codice viene eseguito allo stesso
modo ogni volta. Non c' differenza tra aritmetica ed algebra, ma la programmazione ha altri
operatori che risultano meno familiari.

Nella tavola seguente, gli operatori in cima vengono eseguiti prima di quelli sul fondo.
Perci, un'operazione all'interno delle parentesi verr eseguita per prima ed un'assegnazione verr
eseguita per ultima.
D/Portata delle Variabili
La regola della portata delle variabili viene spiegata facilmente: una variabile creata all'interno di un
blocco (codice racchiuso all'interno di parentesi: { e } ) esiste solamente all'interno di quel blocco.
Ci significa che una variabile creata all'interno del blocco setup( ) pu essere usata solo all'interno
del blocco setup( ), e allo stesso modo, una variabile dichiarata all'interno di draw( ) pu essere
usata solo all'interno del blocco draw( ). L'eccezione a questa regola una variabile dichiarata al di
fuori di setup( ) e draw( ). Queste variabili possono essere usate sia in setup( ) che in draw( )
(o all'interno di ogni altra funzione che hai creato). Pensa all'area che si trova all'esterno di setup( )
e draw( ) come ad un blocco di codice implicito. Noi chiamiamo tutte queste variabili variabili
globali, poich possono essere usate ovunque all'interno del programma.
Chiamiamo una variabile che viene usata solo all'interno di un singolo blocco una variabile locale.
Di seguito ci sono una coppia di esempi di codice che spiegano ulteriormente il concetto.
Il primo:
int i = 12; // Dichiara la variabile globale i ed assegna ad essa 12
void setup() {
size(480, 320);
int i = 24; // Dichiara la variabile locale i ed assegna ad essa 24
println(i); // Stampa 24 sulla console
}
void draw() {
println(i); // Stampa 12 sulla console
}

Ed il secondo:

void setup() {
size(480, 320);
int i = 24; // Dichiara la variabile locale ed assegna ad essa 24
}
void draw() {
println(i); // ERRORE! La variabile i locale in setup()
}

You might also like