SDLGameEngine

src/sgeparticles.c

00001 /*
00002  * Copyright (c) 2007 Heiko Irrgang
00003  *
00004  * The license and distribution terms for this file may be
00005  * found in the file COPYING in this distribution or at
00006  * http://93-interactive.com/cms/products/software/sdl-game-engine/license/
00007  */
00008 
00009 #include <sge.h>
00010 
00011 SGEPARTICLES *sgeParticlesNew(
00012                 void *(*createFunction)(void *),
00013                 Uint32 (*drawFunction)(Uint32, void *),
00014                 void (*freeFunction)(Uint32, void *)
00015 ) {
00016         SGEPARTICLES *ret;
00017         sgeNew(ret, SGEPARTICLES);
00018         ret->runtime=0;
00019         ret->particles=sgeAutoArrayNew(freeFunction);
00020         ret->timeToLive=100;
00021         ret->timeToLiveDistribution=50;
00022         ret->infinite=0;
00023         ret->angle=0;
00024         ret->angleDistribution=20;
00025         ret->gravity=.2;
00026         ret->emission=20;
00027         ret->emissionDistribution=10;
00028         ret->internalEmission=0;
00029         ret->speed=1;
00030         ret->speedDistribution=.2;
00031         ret->create=createFunction;
00032         ret->draw=drawFunction;
00033         ret->drawSurface=screen;
00034         ret->x=0;
00035         ret->y=0;
00036         ret->custom=NULL;
00037         ret->customDestroy=NULL;
00038         return ret;
00039 }
00040 
00041 void sgeParticlesDestroy(SGEPARTICLES *p) {
00042         sgeArrayDestroy(p->particles);
00043         if (p->customDestroy!=NULL) {
00044                 (p->customDestroy(p->custom));
00045         }
00046         sgeFree(p);
00047 }
00048 
00049 void sgeParticlesDraw(SGEPARTICLES *p) {
00050         Uint32 i;
00051         float emission;
00052         p->runtime++;
00053         emission=sgeParticlesGetNewEmission(p);
00054         for (i=0;i<(int)emission;i++) {
00055                 sgeArrayAdd(p->particles, (void *)(p->create)((void *)p));
00056         }
00057         for (i=0;i<p->particles->numberOfElements;i++) {
00058                 i=(p->draw)(i, (void *)p);
00059         }
00060 }
00061 
00062 float sgeParticlesGetNewEmission(SGEPARTICLES *p) {
00063         if (p->emission<1) {
00064                 p->internalEmission+=p->emission;
00065                 if (p->internalEmission>1) {
00066                         p->internalEmission-=1;
00067                         return 1;
00068                 }
00069                 return 0;
00070         }
00071         if (p->emissionDistribution!=0) {
00072                 return p->emission+sgeRandomFloat(-(p->emissionDistribution/2),(p->emissionDistribution));
00073         }
00074         return p->emission;
00075 }
00076 
00077 Uint32 sgeParticlesGetNewTimeToLive(SGEPARTICLES *p) {
00078         if (p->timeToLiveDistribution!=0) {
00079                 Sint32 tmp;
00080                 tmp=p->timeToLive+sgeRandom(-(p->timeToLiveDistribution>>1),(p->timeToLiveDistribution));
00081                 if (tmp>=0) return tmp;
00082                 return 0;
00083         }
00084         return p->timeToLive;
00085 }
00086 
00087 float sgeParticlesGetNewSpeed(SGEPARTICLES *p) {
00088         if (p->speedDistribution!=0) {
00089                 return p->speed+sgeRandomFloat(-p->speedDistribution/2,p->speedDistribution);
00090         }
00091         return p->speed;
00092 }
00093 
00094 float sgeParticlesGetNewAngle(SGEPARTICLES *p) {
00095         if (p->angleDistribution!=0) {
00096                 return p->angle+sgeRandomFloat(-p->angleDistribution/2,p->angleDistribution);
00097         }
00098         return p->angle;
00099 }
00100 
00101 inline float sgeParticlesGetNewX(float x, float angle, float speed) {
00102         return x+cos(M_PI/180*angle)*speed;
00103 }
00104 
00105 inline float sgeParticlesGetNewY(float y, float angle, float speed, float gravity) {
00106         return y+sin(M_PI/180*angle)*speed+gravity;
00107 }
00108 
00109 void *sgePixelParticleNew(void *p) {
00110         SGEPIXELPARTICLE *ret;
00111         SGEPARTICLES *pp=(SGEPARTICLES *)p;
00112         SGEPIXELPARTICLEDATA *data=pp->custom;
00113         Uint8 r,g,b;
00114         sgeNew(ret, SGEPIXELPARTICLE);
00115         ret->x=(float)pp->x;
00116         ret->y=(float)pp->y;
00117         ret->speed=sgeParticlesGetNewSpeed(pp);
00118         ret->angle=sgeParticlesGetNewAngle(pp);
00119         ret->timeToLive=sgeParticlesGetNewTimeToLive(pp);
00120         r=MIN(data->r1,data->r2)+sgeRandom(0,MAX(data->r2,data->r1)-MIN(data->r2,data->r1));
00121         g=MIN(data->g1,data->g2)+sgeRandom(0,MAX(data->g2,data->g1)-MIN(data->g2,data->g1));
00122         b=MIN(data->b1,data->b2)+sgeRandom(0,MAX(data->b2,data->b1)-MIN(data->b2,data->b1));
00123         ret->color=sgeMakeColor(screen,r,g,b,0xff);
00124         ret->gravity=0;
00125         return ret;
00126 }
00127 
00128 void sgePixelParticleDestroy(Uint32 arrayidx, void *particle) {
00129         SGEPIXELPARTICLE *p=(SGEPIXELPARTICLE *)particle;
00130         sgeFree(p);
00131 }
00132 
00133 Uint32 sgePixelParticleDraw(Uint32 arrayidx, void *p) {
00134         SGEPARTICLES *pp=(SGEPARTICLES *)p;
00135         SGEPIXELPARTICLE *particle=sgeArrayGet(pp->particles, arrayidx);
00136 
00137         if (pp->infinite==0) {
00138                 if (particle->timeToLive<1) {
00139                         sgeArrayRemove(pp->particles, arrayidx);
00140                         return arrayidx-1;
00141                 } else {
00142                         particle->timeToLive--;
00143                 }
00144         }
00145         particle->gravity+=pp->gravity;
00146         particle->x=sgeParticlesGetNewX(particle->x, particle->angle, particle->speed);
00147         particle->y=sgeParticlesGetNewY(particle->y, particle->angle, particle->speed, particle->gravity);
00148 
00149         sgeDrawPixel(pp->drawSurface, (int)particle->x, (int)particle->y, particle->color);
00150         return arrayidx;
00151 }
00152 
00153 void sgeParticlesPixelCustomDestroy(void *data) {
00154         SGEPIXELPARTICLEDATA *d=(SGEPIXELPARTICLEDATA *)data;
00155         sgeFree(d);
00156 }
00157 
00158 SGEPARTICLES *sgeParticlesPixelNew(Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2) {
00159         SGEPIXELPARTICLEDATA *data;
00160         SGEPARTICLES *ret=sgeParticlesNew(
00161                         sgePixelParticleNew,
00162                         sgePixelParticleDraw,
00163                         sgePixelParticleDestroy
00164         );
00165         sgeNew(data, SGEPIXELPARTICLEDATA);
00166         data->r1=r1;
00167         data->g1=g1;
00168         data->b1=b1;
00169         data->r2=r2;
00170         data->g2=g2;
00171         data->b2=b2;
00172         ret->custom=(void *)data;
00173         ret->customDestroy=sgeParticlesPixelCustomDestroy;
00174         return ret;
00175 }
00176 
00177 SGEPARTICLES *sgeParticlesSpriteNew(SGESPRITE *sprite) {
00178         SGESPRITEPARTICLEDATA *data;
00179         SGEPARTICLES *ret=sgeParticlesNew(
00180                         sgeSpriteParticleNew,
00181                         sgeSpriteParticleDraw,
00182                         sgeSpriteParticleDestroy
00183         );
00184         sgeNew(data, SGESPRITEPARTICLEDATA);
00185         data->sprite=sprite;
00186         ret->custom=(void *)data;
00187         ret->customDestroy=sgeParticlesSpriteCustomDestroy;
00188         return ret;
00189 }
00190 
00191 void *sgeSpriteParticleNew(void *p) {
00192         SGESPRITEPARTICLE *ret;
00193         SGEPARTICLES *pp=(SGEPARTICLES *)p;
00194         sgeNew(ret, SGESPRITEPARTICLE);
00195         ret->x=(float)pp->x;
00196         ret->y=(float)pp->y;
00197         ret->speed=sgeParticlesGetNewSpeed(pp);
00198         ret->angle=sgeParticlesGetNewAngle(pp);
00199         ret->timeToLive=sgeParticlesGetNewTimeToLive(pp);
00200         ret->gravity=0;
00201         return ret;
00202 }
00203 
00204 void sgeSpriteParticleDestroy(Uint32 arrayidx, void *particle) {
00205         SGESPRITEPARTICLE *p=(SGESPRITEPARTICLE *)particle;
00206         sgeFree(p);
00207 }
00208 
00209 Uint32 sgeSpriteParticleDraw(Uint32 arrayidx, void *p) {
00210         SGEPARTICLES *pp=(SGEPARTICLES *)p;
00211         SGESPRITEPARTICLE *particle=sgeArrayGet(pp->particles, arrayidx);
00212         SGESPRITEPARTICLEDATA *data=pp->custom;
00213 
00214         if (pp->infinite==0) {
00215                 if (particle->timeToLive<1) {
00216                         sgeArrayRemove(pp->particles, arrayidx);
00217                         return arrayidx-1;
00218                 } else {
00219                         particle->timeToLive--;
00220                 }
00221         }
00222         particle->gravity+=pp->gravity;
00223         particle->x=sgeParticlesGetNewX(particle->x, particle->angle, particle->speed);
00224         particle->y=sgeParticlesGetNewY(particle->y, particle->angle, particle->speed, particle->gravity);
00225 
00226         sgeSpriteDrawXY(data->sprite, (int)particle->x, (int)particle->y, pp->drawSurface);
00227         return arrayidx;
00228 }
00229 
00230 void sgeParticlesSpriteCustomDestroy(void *data) {
00231         SGESPRITEPARTICLEDATA *d=(SGESPRITEPARTICLEDATA *)data;
00232         sgeSpriteDestroy(d->sprite);
00233         sgeFree(d);
00234 }
00235 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines