Tema 9

Sistemes de partícules (I)

Dona vida al teu llenç amb centenars d'elements en moviment. Introdueix els vectors amb createVector() i crea el teu primer sistema de partícules des de zero, amb classes i arrays.

Què és un sistema de partícules?

Un sistema de partícules és un conjunt d'elements visuals (partícules) que es comporten de manera similar però independent. S'utilitza per simular fenòmens com:

  • Foc, fum i explosius
  • Pluja, neu i confeti
  • Estrelles i galàxies
  • Eixams d'insectes o bancs de peixos
  • Textures màgiques i efectes visuals

Cada partícula té les seves pròpies propietats (posició, velocitat, color, mida) i s'actualitza autònomament. Per implementar-ho, necessitem dues eines noves: vectors i classes.

Idea clau: En lloc de controlar cada partícula manualment, definim un "comportament" i deixem que l'ordinador gestioni centenars d'elles automàticament.

Vectors: posició i velocitat en un sol paquet

Fins ara, per guardar la posició d'un objecte utilitzàvem dues variables: let x, y;. Amb p5.js podem utilitzar vectors (createVector(x, y)), que agrupen coordenades X i Y en un sol objecte.

Un vector té propietats .x i .y, i mètodes per operar-hi, com .add() per sumar-ne un altre.

let pos = createVector(width/2, height/2); // posició inicial
let vel = createVector(1.5, -1);           // velocitat (dx, dy)

for (let i = 0; i < 30; i++) {
  pos.add(vel);              // pos = pos + vel
  fill(100, 150, 255, 150);
  ellipse(pos.x, pos.y, 8, 8);
}

pos.add(vel) equival a pos.x += vel.x; pos.y += vel.y; però és molt més net i expressiu.

Classes: creant el motlle de les partícules

Una classe és una plantilla per crear objectes. Definim una classe Particula amb un constructor (constructor()) que inicialitza cada partícula, i mètodes com update() i show().

class Particula {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = createVector(random(-2,2), random(-2,2));
  }
  update() {
    this.pos.add(this.vel);
  }
  show() {
    ellipse(this.pos.x, this.pos.y, 10, 10);
  }
}

Concepte clau: this es refereix a la instància concreta (cada partícula individual). Cada partícula té les seves pròpies this.pos i this.vel.

Arrays: emmagatzemar moltes partícules

Per gestionar centenars de partícules, les guardem en un array. Amb .push() afegim noves partícules, i amb un bucle for les recorrem totes per actualitzar-les i dibuixar-les.

let particules = [];

function setup() {
  createCanvas(320, 200);
  for (let i = 0; i < 40; i++) {
    particules.push(new Particula(random(width), random(height)));
  }
}

function draw() {
  background(20, 20, 40, 40); // fons semi-transparent per deixar rastre
  for (let p of particules) {
    p.update();
    p.show();
  }
}

El fons semi-transparent a draw() crea un efecte de "rastre" o "estela" molt atractiu visualment.

Cicle de vida de les partícules

Per evitar que l'array creixi indefinidament (consumint memòria), les partícules han de desaparèixer quan surten del llenç o després d'un cert temps. Afegim una propietat vida i una condició per eliminar-les.

// Al draw(), eliminem partícules mortes (recorrem al revés per seguretat)
for (let i = particules.length - 1; i >= 0; i--) {
  particules[i].update();
  particules[i].show();
  if (particules[i].morta()) {
    particules.splice(i, 1); // elimina la partícula de l'array
  }
}

// A la classe:
morta() {
  return this.vida <= 0 || this.pos.x < 0 || this.pos.x > width 
         || this.pos.y < 0 || this.pos.y > height;
}

Truc: p5.Vector.random2D() retorna un vector unitari aleatori en qualsevol direcció. Multiplicant-lo per una velocitat, obtenim dispersió radial.

Exemples creatius pas a pas

Font de partícules (font màgica)

Les partícules neixen a baix i pugen, com una font d'aigua o espurnes.

// Font de partícules: neixen a (width/2, height) i pugen
constructor(x, y) {
  this.pos = createVector(x, y);
  this.vel = createVector(random(-1, 1), random(-4, -1)); // tendència cap amunt
  this.vida = 255;
}

Pluja generativa

Partícules que cauen des de dalt amb una petita variació horitzontal.

class Gota {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = createVector(0, random(2, 6)); // només component vertical
  }
  show() {
    stroke(150, 200, 255, 200); strokeWeight(2);
    line(this.pos.x, this.pos.y, this.pos.x, this.pos.y+8); // línia vertical
  }
}

Consells per a sistemes de partícules

  • Fons semi-transparent: background(r,g,b,alfa) al draw() en lloc de background() opac crea un efecte de rastre molt estètic.
  • Elimina partícules mortes: recorre l'array al revés (for i = length-1; i>=0; i--) per evitar errors en eliminar elements.
  • Controla la natalitat: utilitza frameCount % N == 0 per crear partícules a intervals regulars.
  • Vectors predefinits: p5.Vector.random2D() per a direccions aleatòries, createVector(0, -1) per a "cap amunt".
  • No abusis: limita el nombre màxim de partícules (per exemple, if (particules.length < 200) ...) per mantenir un bon rendiment.

Exercicis per practicar

  1. Crea un sistema de confeti: partícules quadrades de colors aleatoris que cauen des de dalt amb velocitats i mides diferents.
  2. Implementa un fum que surti d'una xemeneia: partícules circulars grises, semi-transparents, que pugen i s'eixamplen.
  3. Dissenya un eixam de cuques de llum: partícules amb velocitat aleatòria petita i color groc-verdós, que deixen un rastre lluminós.
  4. Fes un generador d'estrelles que apareguin al centre i s'expandeixin en totes direccions, desapareixent lentament.
  5. Repte: Crea un focs artificials simplificat: al fer clic (mousePressed()), un esclat de partícules surt disparat des de baix, explota al cap d'un moment i dispersa partícules filles en cercle.

Reflexió artística

Els sistemes de partícules ens recorden que la bellesa sovint emergeix de la simplicitat multiplicada. Una sola partícula és insignificant, però centenars d'elles, coordinades per regles senzilles, creen espectacles hipnòtics: una cascada, una tempesta de neu, un cel estrellat. Com a artista-programador, el teu rol és dissenyar el comportament individual (velocitat, color, vida) i orquestrar el col·lectiu (quan neixen, on, quantes). La màgia apareix en l'equilibri entre control i caos: petits canvis en els paràmetres produeixen resultats completament diferents. Experimenta amb el fons semi-transparent, juga amb els colors i les velocitats. Cada combinació és un univers visual únic esperant ser descobert.

Mini-projecte del Tema 9

Crea un "Generador d'ambients atmosfèrics" amb les següents característiques:

  • Defineix una classe Particula amb almenys 4 propietats (posició, velocitat, vida, color).
  • Utilitza vectors (createVector) per a la posició i la velocitat.
  • Implementa un cicle de vida complet: les partícules neixen, es mouen, envelleixen i moren (s'eliminen de l'array).
  • Crea almenys dos tipus d'emissió diferents: per exemple, una pluja suau i un núvol de pols al terra, o estrelles fixes i estrelles fugaces.
  • Utilitza un fons semi-transparent per crear l'efecte de rastre.
  • Opcional: fes que la posició de l'emissor segueixi el ratolí (mouseX, mouseY).

Comparteix el teu ambient atmosfèric i explica quina sensació has volgut evocar (calma, tempesta, màgia, misteri...).