#include #include "../include/fx/fire.h" /* Retourne les valeurs sur 8 bits des composantes rouges, vertes et bleues par rapport au format donné */ #define REDVALUE(format, pixel) (Uint8) (((pixel & format->Rmask) << format->Rloss) >> format->Rshift) #define GREENVALUE(format, pixel) (Uint8) (((pixel & format->Gmask) << format->Gloss) >> format->Gshift) #define BLUEVALUE(format, pixel) (Uint8) (((pixel & format->Bmask) << format->Bloss) >> format->Bshift) /* Crée les masques correspondants pour les composantes de couleur données sur 8 bits */ #define REDMASK(format, red) (Uint32) (((red << format->Rshift) >> format->Rloss) & format->Rmask) #define GREENMASK(format, green) (Uint32) (((green << format->Gshift) >> format->Gloss) & format->Gmask) #define BLUEMASK(format, blue) (Uint32) (((blue << format->Bshift) >> format->Bloss) & format->Bmask) /* Retourne la valeur d'un pixel selon ses 3 composantes de couleur, données sur 8 bits */ #define MAKEPIXEL(format, red, green, blue) (Uint32) (REDMASK(format, red) | GREENMASK(format, green) | BLUEMASK(format, blue)) /* Lit et affecte un pixel à partir d'un pointeur */ #define READPIXEL(pointer, pixel) { pixel = *(Uint16 *)(pointer) + (*(Uint8 *)((pointer) + 2) << 16); } #define STOREPIXEL(pointer, pixel) { *(Uint16 *)(pointer) = (Uint16)(pixel); *(Uint8 *)((pointer) + 2) = (Uint8)((pixel) >> 16) & 0xff; } /* Effet de foyer */ void fireRoot(struct fire_ *fire_t) { Uint32 i, j; /* Pour chaque ligne du foyer, la vivacité détermine combien de pixels mettre à jour */ for (j = fire_t->rootRect->y; j < fire_t->rootRect->y + fire_t->rootRect->h; j++) for (i = 0; i < fire_t->vivacity; i++) { /* Déterminer la valeur de chaque composante en fonction de l'intensité - elles auront les mêmes valeurs, ce qui nous fournira un gris */ Uint8 color = (fire_t->intensity + (rand() % (256 - fire_t->intensity))); /* Choisir une position au hasard */ Uint32 position = (rand() % fire_t->rootRect->w) + fire_t->rootRect->x; /* Et y affecter le pixel */ STOREPIXEL(fire_t->surface->pixels + j * fire_t->surface->pitch + position * fire_t->surface->format->BytesPerPixel, MAKEPIXEL(fire_t->surface->format, color, color, color)); } /* Même chose avec la résistance - on éteint aléatoirement des pixels */ for (j = fire_t->rootRect->y; j < fire_t->rootRect->y + fire_t->rootRect->h; j++) for (i = 0; i < fire_t->resistance; i++) { Uint32 position = (rand() % fire_t->rootRect->w) + fire_t->rootRect->x; STOREPIXEL(fire_t->surface->pixels + j * fire_t->surface->pitch + (position * fire_t->surface->format->BytesPerPixel), 0); } } /* Effet de feu */ void fire(struct fire_ *fire_t) { Uint32 i, j; /* Chaque pixel de la zone doit être mis à jour */ for (j = fire_t->fireRect->y; j < fire_t->fireRect->y + fire_t->fireRect->h; j++) for (i = fire_t->fireRect->x; i < fire_t->fireRect->x + fire_t->fireRect->w; i++) { /* Pointeur vers le pixel courant */ void * curpixel; /* Nouvelle valeur du pixel courant */ Uint32 pixvalue = 0; /* Addition des valeurs des composantes rouges, vertes et bleues des pixels adjacents au pixel courant */ Uint16 red = 0, green = 0, blue = 0; /* Le pixel à mettre à jour */ curpixel = fire_t->surface->pixels + (fire_t->surface->pitch * j) + (i * fire_t->surface->format->BytesPerPixel); /* Addition des composantes des 4 pixels adjacents */ /* Inférieur gauche */ if (i > 0) { READPIXEL(curpixel + fire_t->surface->pitch - fire_t->surface->format->BytesPerPixel, pixvalue); red += REDVALUE(fire_t->surface->format, pixvalue); green += GREENVALUE(fire_t->surface->format, pixvalue); blue += BLUEVALUE(fire_t->surface->format, pixvalue); } /* Inférieur */ READPIXEL(curpixel + fire_t->surface->pitch, pixvalue); red += REDVALUE(fire_t->surface->format, pixvalue); green += GREENVALUE(fire_t->surface->format, pixvalue); blue += BLUEVALUE(fire_t->surface->format, pixvalue); /* Deux lignes en dessous */ READPIXEL(curpixel + fire_t->surface->pitch * 2, pixvalue); red += REDVALUE(fire_t->surface->format, pixvalue); green += GREENVALUE(fire_t->surface->format, pixvalue); blue += BLUEVALUE(fire_t->surface->format, pixvalue); /* Inférieur droit */ if (i < fire_t->surface->w - 1) { READPIXEL(curpixel + fire_t->surface->pitch + fire_t->surface->format->BytesPerPixel, pixvalue); red += REDVALUE(fire_t->surface->format, pixvalue); green += GREENVALUE(fire_t->surface->format, pixvalue); blue += BLUEVALUE(fire_t->surface->format, pixvalue); } /* Altération des composantes afin d'obtenir la teinte de la flamme */ if (red > 2) red -= 2; else red = 0; if (green > 5) green -= 5; else green = 0; if (blue > 150) blue -= 150; else blue = 0; /* Division par quatre de l'addition des composantes */ red /= 4; green /= 4; blue /= 4; /* Affectation de la nouvelle valeur du pixel */ STOREPIXEL(curpixel, MAKEPIXEL(fire_t->surface->format, red, green, blue)); } }