
Gli effetti particellari sono una componente essenziale nell’effettistica dei videogiochi di qualunque tipo. Usati con un po’ di fantasia possono essere un forte strumento per dare un tocco di originalità nei videogiochi, ma devono essere usati con discrezione, perché possono compromettere la fluidità del progetto.
Ma cos’è un effetto particellare? E’ semplicemente qualcosa creato dalla generazione di numerosissime particelle che posso riprodurre effetti tipici come fumo, fuoco, neve, ma smanettando un po' si possono ottenere risultati veramente apprezzabili e originali.
Prima di passare al codice, un po’ di teoria: l’effetto particellare, sia in Irrlicht, sia in qualunque programma di grafica, ha bisogno di un emettitore. Praticamente “qualcosa” che genera particelle. Esso gestisce il numero di particelle che vengono generate al secondo, la direzione, la velocità e la vita. Ogni particella ha una dimensione e una forma, data frequentemente da una texture. La singola particella ha una utilissima particolarità: è un quadrato che si orienta sempre nella direzione dell’osservatore, perciò è relativamente leggero in tempo di rendering.
Passiamo ora ad Irrlicht! Irrlicht è un motore grafico che punta molto sugli effetti. E a mio parere gli effetti particellari non deludono le aspettative: ecco un esempio di codice:
CREAZIONE DI UN EFFETTO PARTICELLARE CHE SIMULA IL FUOCO
scene::IParticleSystemSceneNode* ps;
ps = smgr->addParticleSystemSceneNode(false);
ps->setPosition(core::vector3df(Xposition,130,Yposition));
ps->setScale(core::vector3df(1.8,1.8,1.8));
ps->setParticleSize(core::dimension2d<f32>(20.0f, 20.0f));
scene::IParticleEmitter* em = ps->createBoxEmitter(
core::aabbox3d<f32>(-6,0,-6,6,1,6),
core::vector3df(0.05f,0.1f,0.0f),
100,500,
video::SColor(0,255,255,255), video::SColor(0,255,255,255),
100,500);
ps->setEmitter(em);
em->drop();
scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
ps->addAffector(paf);
paf->drop();
ps->setMaterialFlag(video::EMF_LIGHTING, false);
ps->setMaterialTexture(0, driver->getTexture("fire.bmp"));
ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
ed ecco il risultato (ovviamente senza colonna):

Analizziamo ora meglio il codice:
scene::IParticleSystemSceneNode* ps;
ps = smgr->addParticleSystemSceneNode(false);
ps->setPosition(core::vector3df(Xposition,130,Yposition));
ps->setScale(core::vector3df(1.8,1.8,1.8));
ps->setParticleSize(core::dimension2d<f32>(20.0f, 20.0f));
Qui nella prima riga creiamo un puntatore a IparticleSystemSceneNode con il nome di “ps”.
Nella seconda riga assegnamo al puntatore “ps” un nodo di tipo “sistema particellare”. Il “false” negli argomenti della funzione sta a settare il parametro se usare o no un “default emitter” ossia un emettitore standard. In questo caso noi mettiamo “false” perché vogliamo settare noi nei dettagli l’emettitore.
Le seguenti tre righe sono piuttosto intuitive, settiamo la posizione del sistema particellare, settiamo la scala, e la dimensione di ogni singola particella.
scene::IParticleEmitter* em = ps->createBoxEmitter(
core::aabbox3d<f32>(-6,0,-6,6,1,6),
core::vector3df(0.05f,0.1f,0.0f),
100,500,
video::SColor(0,255,255,255), video::SColor(0,255,255,255),
100,500,0);
Questa è la parte più importante: si crea un emettitore “em” tramite il sistema particellare “ps” e si settono i vari parametri. In ordine:
-Dimensione della box da dove vengono create le particelle;
-Direzione che prendono le particelle emesse, notare che se al posto di vector3df(0,1,0) si
mette vector3df(0,10,0), la direzione sarà uguale ma cambierà la velocità delle particelle.
-Numero minimo di particelle che vengono emesse in un secondo;
-Numero massimo di particelle che vengono emesse in un secono. Il computer genera un
numero casuale tra il valore minimo e massimo;
-Colore iniziale minimo delle particelle;
-Colore iniziale massimo delle particelle. Questo valore, come il precedente, in questo
caso non ha senso, perché successivamente aggiungeremo una texture alle particelle;
-Vita minima delle particelle;
-Vita massima delle particelle. Analogamente al numero di particelle al secondo, il
computer genera un numero casuale tra il valore minimo e massimo;
-Parametro che esprime la massima deviazione delle particelle dall’asse.
ps->setEmitter(em);
em->drop();
Qui assegniamo a “ps” l’emettitore appena settato e deallochiamo “em”, perché una volta assegnato l’emettitore a “ps”, “ps” si copia le informazioni necessarie e “em” occuperebbe memoria inutile. (salvo caso che si voglia riutilizzare il dato emettitore).
scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
ps->addAffector(paf);
paf->drop();
Per dare la forma conica tipica del fuoco, creiamo un “FadeOutParticleAffector”, e dopo averlo assegnato al sistema particellare lo deallochiamo.
ps->setMaterialFlag(video::EMF_LIGHTING, false);
ps->setMaterialTexture(0, driver->getTexture("fire.bmp"));
ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
Queste ultime tre righe settano il tipo di illuminazione, la texture da utlizzare e impostano la trasparenza nelle zone nere della texture.
CREAZIONE DI UN EFFETTO PARTICELLARE CHE SIMULA LA NEVE
scene::IParticleSystemSceneNode* neve = 0;
neve = smgr->addParticleSystemSceneNode(false);
neve->setPosition(core::vector3df(0,500,2800));
neve->setScale(core::vector3df(2,2,2));
neve->setParticleSize(core::dimension2d<f32>(5.0f, 5.0f));
scene::IParticleEmitter* emit = neve->createBoxEmitter(
core::aabbox3d<f32>(-1000,0,-1000,1000,200,1000),
core::vector3df(0.1f,0.1f,0.0f),
100,500,
video::SColor(0,255,255,255), video::SColor(0,255,255,255),
10000,20000,10);
neve->setEmitter(emit);
emit->drop();
scene::IParticleAffector* Gra = neve->createGravityAffector (vector3df(0,-0.1,0),10);
neve->addAffector(Gra);
Gra->drop();
neve->setMaterialFlag(video::EMF_LIGHTING, false);
neve->setMaterialTexture(0, driver->getTexture("neve.bmp"));
neve->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);

Come si può notare ci sono dei piccoli ma essenziali differenze dal codice utilizzato per il fuoco. Innanzitutto è aumentato l’area di generazione delle particelle e la vita . Al posto di un “FadeOutParticleAffector” viene creato un “GravityAffector” che simula la gravità che fa cadere le particelle. Infine ovviamente si sostituisce la texture da utilizzare.
by Cadue
Ottimo tutorial cadue!
Ce ne vorrebbero di altri fatti così ^_^
Fantastico!! non vedo l’ora di provare a far qualcosa!!
Ottimo tutorial, ma sono curioso di vedere la mappa fire.bmp com’e’ fatta!
Il fuoco non mi viene bene, forse è colpa della mia telecamera/proiezione.
La neve invece è fantastica!!!