diff options
Diffstat (limited to 'src/post/goom/flying_stars_fx.c')
-rw-r--r-- | src/post/goom/flying_stars_fx.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/src/post/goom/flying_stars_fx.c b/src/post/goom/flying_stars_fx.c new file mode 100644 index 000000000..72231e9c8 --- /dev/null +++ b/src/post/goom/flying_stars_fx.c @@ -0,0 +1,280 @@ +#include "goom_fx.h" +#include "goom_plugin_info.h" +#include "goom_tools.h" + +#include "mathtools.h" + +/* TODO:-- FAIRE PROPREMENT */ +#define NCOL 15 +static const int colval[] = { + 0x1416181a, + 0x1419181a, + 0x141f181a, + 0x1426181a, + 0x142a181a, + 0x142f181a, + 0x1436181a, + 0x142f1819, + 0x14261615, + 0x13201411, + 0x111a100a, + 0x0c180508, + 0x08100304, + 0x00050101, + 0x0 +}; + +/* The different modes of the visual FX. + * Put this values on fx_mode */ +#define FIREWORKS_FX 0 +#define RAIN_FX 1 +#define FOUNTAIN_FX 2 +#define LAST_FX 3 + +typedef struct _FS_STAR { + float x,y; + float vx,vy; + float ax,ay; + float age,vage; +} Star; + +typedef struct _FS_DATA{ + + int fx_mode; + int nbStars; + + int maxStars; + Star *stars; + + float min_age; + float max_age; + + PluginParam min_age_p; + PluginParam max_age_p; + PluginParam nbStars_p; + PluginParam nbStars_limit_p; + PluginParam fx_mode_p; + + PluginParameters params; +} FSData; + +static void fs_init(VisualFX *_this) { + + FSData *data; + data = (FSData*)malloc(sizeof(FSData)); + + data->fx_mode = FIREWORKS_FX; + data->maxStars = 4096; + data->stars = (Star*)malloc(data->maxStars * sizeof(Star)); + data->nbStars = 0; + + data->max_age_p = secure_i_param ("Fireworks Smallest Bombs"); + IVAL(data->max_age_p) = 80; + IMIN(data->max_age_p) = 0; + IMAX(data->max_age_p) = 100; + ISTEP(data->max_age_p) = 1; + + data->min_age_p = secure_i_param ("Fireworks Largest Bombs"); + IVAL(data->min_age_p) = 99; + IMIN(data->min_age_p) = 0; + IMAX(data->min_age_p) = 100; + ISTEP(data->min_age_p) = 1; + + data->nbStars_limit_p = secure_i_param ("Max Number of Particules"); + IVAL(data->nbStars_limit_p) = 512; + IMIN(data->nbStars_limit_p) = 0; + IMAX(data->nbStars_limit_p) = data->maxStars; + ISTEP(data->nbStars_limit_p) = 64; + + data->fx_mode_p = secure_i_param ("FX Mode"); + IVAL(data->fx_mode_p) = data->fx_mode; + IMIN(data->fx_mode_p) = 1; + IMAX(data->fx_mode_p) = 3; + ISTEP(data->fx_mode_p) = 1; + + data->nbStars_p = secure_f_feedback ("Number of Particules (% of Max)"); + + data->params = plugin_parameters ("Particule System", 7); + data->params.params[0] = &data->fx_mode_p; + data->params.params[1] = &data->nbStars_limit_p; + data->params.params[2] = 0; + data->params.params[3] = &data->min_age_p; + data->params.params[4] = &data->max_age_p; + data->params.params[5] = 0; + data->params.params[6] = &data->nbStars_p; + + _this->params = &data->params; + _this->fx_data = (void*)data; +} + +static void fs_free(VisualFX *_this) { + free (_this->fx_data); +} + + +/** + * Cree une nouvelle 'bombe', c'est a dire une particule appartenant a une fusee d'artifice. + */ +static void addABomb (FSData *fs, int mx, int my, float radius, float vage, float gravity, PluginInfo *info) { + + int i = fs->nbStars; + float ro; + int theta; + + if (fs->nbStars >= fs->maxStars) + return; + fs->nbStars++; + + fs->stars[i].x = mx; + fs->stars[i].y = my; + + ro = radius * (float)goom_irand(info->gRandom,100) / 100.0f; + ro *= (float)goom_irand(info->gRandom,100)/100.0f + 1.0f; + theta = goom_irand(info->gRandom,256); + + fs->stars[i].vx = ro * cos256[theta]; + fs->stars[i].vy = -0.2f + ro * sin256[theta]; + + fs->stars[i].ax = 0; + fs->stars[i].ay = gravity; + + fs->stars[i].age = 0; + if (vage < fs->min_age) + vage=fs->min_age; + fs->stars[i].vage = vage; +} + + +/** + * Met a jour la position et vitesse d'une particule. + */ +static void updateStar (Star *s) { + s->x+=s->vx; + s->y+=s->vy; + s->vx+=s->ax; + s->vy+=s->ay; + s->age+=s->vage; +} + + +/** + * Ajoute de nouvelles particules au moment d'un evenement sonore. + */ +static void fs_sound_event_occured(VisualFX *_this, PluginInfo *info) { + + FSData *data = (FSData*)_this->fx_data; + int i; + + int max = (int)((1.0f+info->sound.goomPower)*goom_irand(info->gRandom,150)) + 100; + float radius = (1.0f+info->sound.goomPower) * (float)(goom_irand(info->gRandom,150)+50)/300; + int mx = goom_irand(info->gRandom,info->screen.width); + int my; + float vage, gravity = 0.02f; + + switch (data->fx_mode) { + case FIREWORKS_FX: + my = goom_irand(info->gRandom,info->screen.height); + vage = data->max_age * (1.0f - info->sound.goomPower); + break; + case RAIN_FX: + my = -(info->screen.height/3)-goom_irand(info->gRandom,info->screen.width/3); + radius *= 1.5; + vage = 0.002f; + break; + case FOUNTAIN_FX: + my = info->screen.height+2; + vage = 0.001f; + radius += 1.0f; + mx = info->screen.width / 2; + gravity = 0.04f; + break; + default: + return; + /* my = i R A N D (info->screen.height); vage = 0.01f; */ + } + + radius *= info->screen.height / 200.0f; /* why 200 ? because the FX was developped on 320x200 */ + max *= info->screen.height / 200.0f; + + if (info->sound.timeSinceLastBigGoom < 1) { + radius *= 1.5; + max *= 2; + } + for (i=0;i<max;++i) + addABomb (data,mx,my,radius,vage,gravity,info); +} + + +/** + * Main methode of the FX. + */ +static void fs_apply(VisualFX *_this, Pixel *src, Pixel *dest, PluginInfo *info) { + + int i; + int col; + FSData *data = (FSData*)_this->fx_data; + + /* Get the new parameters values */ + data->min_age = 1.0f - (float)IVAL(data->min_age_p)/100.0f; + data->max_age = 1.0f - (float)IVAL(data->max_age_p)/100.0f; + FVAL(data->nbStars_p) = (float)data->nbStars / (float)data->maxStars; + data->nbStars_p.change_listener(&data->nbStars_p); + data->maxStars = IVAL(data->nbStars_limit_p); + data->fx_mode = IVAL(data->fx_mode_p); + + /* look for events */ + if (info->sound.timeSinceLastGoom < 1) { + fs_sound_event_occured(_this, info); + if (goom_irand(info->gRandom,20)==1) { + IVAL(data->fx_mode_p) = goom_irand(info->gRandom,(LAST_FX*3)); + data->fx_mode_p.change_listener(&data->fx_mode_p); + } + } + + /* update particules */ + for (i=0;i<data->nbStars;++i) { + updateStar(&data->stars[i]); + + /* dead particule */ + if (data->stars[i].age>=NCOL) + continue; + + /* choose the color of the particule */ + col = colval[(int)data->stars[i].age]; + + /* draws the particule */ + info->methods.draw_line(dest,(int)data->stars[i].x,(int)data->stars[i].y, + (int)(data->stars[i].x-data->stars[i].vx*6), + (int)(data->stars[i].y-data->stars[i].vy*6), + col, + (int)info->screen.width, (int)info->screen.height); + info->methods.draw_line(dest,(int)data->stars[i].x,(int)data->stars[i].y, + (int)(data->stars[i].x-data->stars[i].vx*2), + (int)(data->stars[i].y-data->stars[i].vy*2), + col, + (int)info->screen.width, (int)info->screen.height); + } + + /* look for dead particules */ + for (i=0;i<data->nbStars;) { + + if ((data->stars[i].x > info->screen.width + 64) + ||((data->stars[i].vy>=0)&&(data->stars[i].y - 16*data->stars[i].vy > info->screen.height)) + ||(data->stars[i].x < -64) + ||(data->stars[i].age>=NCOL)) { + data->stars[i] = data->stars[data->nbStars-1]; + data->nbStars--; + } + else ++i; + } +} + +VisualFX flying_star_create() { + VisualFX vfx = { + init: fs_init, + free: fs_free, + apply: fs_apply, + fx_data: 0 + }; + return vfx; +} |