Operacions amb formes
Aprèn a combinar formes simples per construir figures complexes. Crea els teus propis "blocs de construcció" amb funcions, i organitza el codi amb push() i pop().
De formes simples a estructures complexes
Fins ara hem dibuixat formes independents: un cercle, un rectangle, un triangle. Però qualsevol objecte real es compon de múltiples peces. Per exemple, una cara té ulls, nas i boca. Un cotxe té carrosseria, rodes i finestres.
El repte és agrupar formes per crear entitats amb significat. Això es pot fer directament dibuixant diverses formes al draw(), però aviat veurem tècniques per organitzar millor el codi.
// Cara completa feta de formes simples
fill(255,220,200); ellipse(100,100,120,120); // cap
fill(255); ellipse(75,85,25,25); ellipse(125,85,25,25); // blanc dels ulls
fill(0); ellipse(75,85,10,10); ellipse(125,85,10,10); // pupil·les
fill(255,100,100); arc(100,120,40,25,0,PI); // boca somrient
De moment tot està barrejat al draw(). Si volem dibuixar diverses cares, hauríem de repetir el codi... tret que fem servir funcions.
Funcions personalitzades: els teus propis blocs
Una funció és un bloc de codi amb nom que podem cridar (invocar) tantes vegades com vulguem. Podem crear funcions que dibuixin un objecte complet, passant paràmetres com la posició o la mida.
Exemple: creem la funció dibuixaCara(x, y) per dibuixar una cara a la posició que vulguem.
function setup() {
createCanvas(300, 200);
background(240);
}
function draw() {
dibuixaCara(90, 100);
dibuixaCara(210, 100);
}
// Funció que dibuixa una cara a (x,y)
function dibuixaCara(x, y) {
fill(255,220,200); ellipse(x, y, 80, 80);
fill(255); ellipse(x-15, y-10, 18, 18); ellipse(x+15, y-10, 18, 18);
fill(0); ellipse(x-15, y-10, 8, 8); ellipse(x+15, y-10, 8, 8);
fill(255,100,100); arc(x, y+15, 30, 18, 0, PI);
}
Avantatge: Ara podem dibuixar cares a qualsevol lloc sense repetir codi. Si volem canviar el disseny, només ho fem un cop.
Paràmetres: fent les funcions més flexibles
Podem passar més paràmetres a les nostres funcions, com la mida, el color o qualsevol altra propietat. Així una mateixa funció pot generar molta varietat.
// Funció que dibuixa una flor amb paràmetres de posició, mida i color
function dibuixaFlor(x, y, mida, col) {
fill(col); noStroke();
for (let i = 0; i < 6; i++) {
let angle = map(i, 0, 6, 0, TWO_PI);
let px = x + cos(angle) * mida * 0.6;
let py = y + sin(angle) * mida * 0.6;
ellipse(px, py, mida * 0.5, mida * 0.5);
}
fill(255, 255, 0);
ellipse(x, y, mida * 0.4, mida * 0.4);
}
push() i pop(): dibuixar en capes
Quan fem servir funcions per dibuixar objectes, sovint volem canviar temporalment propietats (colors, gruixos, o més endavant transformacions) sense afectar la resta del dibuix. push() desa l'estat actual i pop() el restaura.
S'introdueixen aquí perquè són essencials per a funcions netes, tot i que les transformacions fortes les veurem al Tema 7.
function dibuixaCasa(x, y, escala, col) {
push(); // guardem estat (colors, transformacions...)
translate(x, y); // movem origen a (x,y)
scale(escala); // escalem (Tema 7 en detall)
fill(col); noStroke();
rect(-25, 0, 50, 40); // cos de la casa
triangle(-30, 0, 0, -25, 30, 0); // teulada
fill(120,80,60); rect(-8, -15, 16, 25); // porta
fill(200,230,255); rect(10, -30, 12, 12); // finestra
pop(); // restablim estat original
}
Sense push()/pop(), els canvis de translate() i scale() s'acumularien i descol·locarien la segona casa.
Composar escenes amb funcions
Un cop tenim funcions per a objectes individuals (cara, casa, arbre, cotxe...), podem combinar-les per crear escenes completes amb molt poc codi.
function draw() {
background(135,206,235); // cel
fill(100,180,100); rect(0,160,width,40); // terra
fill(255,255,0); ellipse(320,40,40,40); // sol
dibuixaCasa(50, 150, 0.8, color(255,220,180));
dibuixaCasa(130, 150, 1, color(255,200,200));
dibuixaCasa(230, 150, 0.6, color(200,220,255));
dibuixaCasa(300, 150, 0.9, color(255,240,200));
}
Exemples creatius pas a pas
Bosc modular
Creem una funció arbre(x, y, h) i la cridem moltes vegades amb paràmetres aleatoris.
function arbre(x, y, h) {
push(); translate(x, y);
fill(120,80,50); rect(-4, 0, 8, -h);
fill(30,150,70);
ellipse(0, -h, h*0.5, h*0.6);
ellipse(-8, -h-10, h*0.4, h*0.5);
ellipse(8, -h-10, h*0.4, h*0.5);
pop();
}
Skyline urbà
Funció edifici(x, ample, alt) per construir una ciutat amb varietat d'edificis.
function edifici(x, ample, alcada) {
let y = height - alcada;
push(); noStroke();
fill(60,60,100); rect(x, y, ample, alcada);
for (let wy = y+10; wy < height; wy += 15) {
for (let wx = x+5; wx < x+ample-5; wx += 10) {
fill(255,255,200, random(100,255));
rect(wx, wy, 5, 5);
}
}
pop();
}
Pensar modularment: el poder de les funcions
Quan descomposem un dibuix complex en funcions més petites, estem aplicant el principi de modularitat. Això fa que el codi sigui:
- Més llegible: cada funció té un nom descriptiu.
- Reutilitzable: podem fer servir la mateixa funció en múltiples projectes.
- Fàcil de modificar: si volem canviar el disseny d'un element, només toquem la seva funció.
- Escalable: podem combinar funcions per crear escenes cada cop més riques.
Exercicis per practicar
- Dissenya una funció
cotxe(x, y, colorCarrosseria)amb almenys 6 formes (carrosseria, rodes, finestres, llums). - Crea una funció
ninotDeNeu(x, y, mida)amb tres cercles superposats i petits detalls (ulls, nas de pastanaga, barret). - Utilitza
push()ipop()per dibuixar 5 estrelles de mar de colors i mides diferents repartides per la platja. - Escriu una funció
vaixell(x, y)que dibuixi un veler. Després crida-la diverses vegades per crear una regata. - Repte: Dissenya un "monstre" personalitzable amb paràmetres: nombre d'ulls, color del cos, mida de les dents i posició. Fes-ne una família de 3 monstres diferents.
Reflexió artística
L'art no és només el resultat final, sinó també l'arquitectura del procés creatiu. Quan dissenyes una funció per dibuixar un objecte, estàs prenent decisions sobre què és essencial i què és accessori, sobre com es relacionen les parts amb el tot. Aquesta manera de pensar –descomposar, parametritzar, recombinar– és la base del pensament computacional aplicat a l'art. Et permetrà crear obres cada cop més ambicioses sense perdre't en la complexitat. Les funcions són els teus pinzells personalitzats: dissenya'ls amb cura i el teu estil brillarà en cada traç.
Mini-projecte del Tema 6
Crea una "Escena modular interactiva" amb les següents condicions:
- Defineix almenys 3 funcions personalitzades que dibuixin objectes diferents (casa, arbre, vehicle, persona, núvol, animal...).
- Cada funció ha de tenir almenys 3 paràmetres (posició, mida, color...).
- Utilitza
push()ipop()a dins de cada funció per aïllar canvis d'estil o transformacions. - Compon una escena completa (paisatge, ciutat, fons marí, espai exterior...) al
draw()cridant les funcions múltiples vegades. - Opcional: fes que un dels paràmetres depengui del ratolí (
mouseXomouseY) per afegir interactivitat.
Comparteix la teva escena modular i les funcions que has creat. Explica com has decidit descomposar els elements i quins paràmetres has triat.