/xbmc/visualizations/Goom/goom2k4-0/src/flying_stars_fx.c

http://github.com/xbmc/xbmc · C · 316 lines · 221 code · 53 blank · 42 comment · 14 complexity · 5e455c1fe0523f940fd6e69a839f4fbf MD5 · raw file

  1. #include "goom_fx.h"
  2. #include "goom_plugin_info.h"
  3. #include "goom_tools.h"
  4. #include "mathtools.h"
  5. /* TODO:-- FAIRE PROPREMENT... BOAH... */
  6. #define NCOL 15
  7. /*static const int colval[] = {
  8. 0xfdf6f5,
  9. 0xfae4e4,
  10. 0xf7d1d1,
  11. 0xf3b6b5,
  12. 0xefa2a2,
  13. 0xec9190,
  14. 0xea8282,
  15. 0xe87575,
  16. 0xe46060,
  17. 0xe14b4c,
  18. 0xde3b3b,
  19. 0xdc2d2f,
  20. 0xd92726,
  21. 0xd81619,
  22. 0xd50c09,
  23. 0
  24. };
  25. */
  26. static const int colval[] = {
  27. 0x1416181a,
  28. 0x1419181a,
  29. 0x141f181a,
  30. 0x1426181a,
  31. 0x142a181a,
  32. 0x142f181a,
  33. 0x1436181a,
  34. 0x142f1819,
  35. 0x14261615,
  36. 0x13201411,
  37. 0x111a100a,
  38. 0x0c180508,
  39. 0x08100304,
  40. 0x00050101,
  41. 0x0
  42. };
  43. /* The different modes of the visual FX.
  44. * Put this values on fx_mode */
  45. #define FIREWORKS_FX 0
  46. #define RAIN_FX 1
  47. #define FOUNTAIN_FX 2
  48. #define LAST_FX 3
  49. typedef struct _FS_STAR {
  50. float x,y;
  51. float vx,vy;
  52. float ax,ay;
  53. float age,vage;
  54. } Star;
  55. typedef struct _FS_DATA{
  56. int fx_mode;
  57. int nbStars;
  58. int maxStars;
  59. Star *stars;
  60. float min_age;
  61. float max_age;
  62. PluginParam min_age_p;
  63. PluginParam max_age_p;
  64. PluginParam nbStars_p;
  65. PluginParam nbStars_limit_p;
  66. PluginParam fx_mode_p;
  67. PluginParameters params;
  68. } FSData;
  69. static void fs_init(VisualFX *_this, PluginInfo *info) {
  70. FSData *data;
  71. data = (FSData*)malloc(sizeof(FSData));
  72. data->fx_mode = FIREWORKS_FX;
  73. data->maxStars = 4096;
  74. data->stars = (Star*)malloc(data->maxStars * sizeof(Star));
  75. data->nbStars = 0;
  76. data->max_age_p = secure_i_param ("Fireworks Smallest Bombs");
  77. IVAL(data->max_age_p) = 80;
  78. IMIN(data->max_age_p) = 0;
  79. IMAX(data->max_age_p) = 100;
  80. ISTEP(data->max_age_p) = 1;
  81. data->min_age_p = secure_i_param ("Fireworks Largest Bombs");
  82. IVAL(data->min_age_p) = 99;
  83. IMIN(data->min_age_p) = 0;
  84. IMAX(data->min_age_p) = 100;
  85. ISTEP(data->min_age_p) = 1;
  86. data->nbStars_limit_p = secure_i_param ("Max Number of Particules");
  87. IVAL(data->nbStars_limit_p) = 512;
  88. IMIN(data->nbStars_limit_p) = 0;
  89. IMAX(data->nbStars_limit_p) = data->maxStars;
  90. ISTEP(data->nbStars_limit_p) = 64;
  91. data->fx_mode_p = secure_i_param ("FX Mode");
  92. IVAL(data->fx_mode_p) = data->fx_mode;
  93. IMIN(data->fx_mode_p) = 1;
  94. IMAX(data->fx_mode_p) = 3;
  95. ISTEP(data->fx_mode_p) = 1;
  96. data->nbStars_p = secure_f_feedback ("Number of Particules (% of Max)");
  97. data->params = plugin_parameters ("Particule System", 7);
  98. data->params.params[0] = &data->fx_mode_p;
  99. data->params.params[1] = &data->nbStars_limit_p;
  100. data->params.params[2] = 0;
  101. data->params.params[3] = &data->min_age_p;
  102. data->params.params[4] = &data->max_age_p;
  103. data->params.params[5] = 0;
  104. data->params.params[6] = &data->nbStars_p;
  105. _this->params = &data->params;
  106. _this->fx_data = (void*)data;
  107. }
  108. static void fs_free(VisualFX *_this) {
  109. FSData *data = (FSData*)_this->fx_data;
  110. free (data->stars);
  111. free (data->params.params);
  112. free (data);
  113. }
  114. /**
  115. * Cree une nouvelle 'bombe', c'est a dire une particule appartenant a une fusee d'artifice.
  116. */
  117. static void addABomb (FSData *fs, int mx, int my, float radius, float vage, float gravity, PluginInfo *info) {
  118. int i = fs->nbStars;
  119. float ro;
  120. int theta;
  121. if (fs->nbStars >= fs->maxStars)
  122. return;
  123. fs->nbStars++;
  124. fs->stars[i].x = mx;
  125. fs->stars[i].y = my;
  126. ro = radius * (float)goom_irand(info->gRandom,100) / 100.0f;
  127. ro *= (float)goom_irand(info->gRandom,100)/100.0f + 1.0f;
  128. theta = goom_irand(info->gRandom,256);
  129. fs->stars[i].vx = ro * cos256[theta];
  130. fs->stars[i].vy = -0.2f + ro * sin256[theta];
  131. fs->stars[i].ax = 0;
  132. fs->stars[i].ay = gravity;
  133. fs->stars[i].age = 0;
  134. if (vage < fs->min_age)
  135. vage=fs->min_age;
  136. fs->stars[i].vage = vage;
  137. }
  138. /**
  139. * Met a jour la position et vitesse d'une particule.
  140. */
  141. static void updateStar (Star *s) {
  142. s->x+=s->vx;
  143. s->y+=s->vy;
  144. s->vx+=s->ax;
  145. s->vy+=s->ay;
  146. s->age+=s->vage;
  147. }
  148. /**
  149. * Ajoute de nouvelles particules au moment d'un evenement sonore.
  150. */
  151. static void fs_sound_event_occured(VisualFX *_this, PluginInfo *info) {
  152. FSData *data = (FSData*)_this->fx_data;
  153. int i;
  154. int max = (int)((1.0f+info->sound.goomPower)*goom_irand(info->gRandom,150)) + 100;
  155. float radius = (1.0f+info->sound.goomPower) * (float)(goom_irand(info->gRandom,150)+50)/300;
  156. int mx;
  157. int my;
  158. float vage, gravity = 0.02f;
  159. switch (data->fx_mode) {
  160. case FIREWORKS_FX:
  161. {
  162. double dx,dy;
  163. do {
  164. mx = goom_irand(info->gRandom,info->screen.width);
  165. my = goom_irand(info->gRandom,info->screen.height);
  166. dx = (mx - info->screen.width/2);
  167. dy = (my - info->screen.height/2);
  168. } while (dx*dx + dy*dy < (info->screen.height/2)*(info->screen.height/2));
  169. vage = data->max_age * (1.0f - info->sound.goomPower);
  170. }
  171. break;
  172. case RAIN_FX:
  173. mx = goom_irand(info->gRandom,info->screen.width);
  174. if (mx > info->screen.width/2)
  175. mx = info->screen.width;
  176. else
  177. mx = 0;
  178. my = -(info->screen.height/3)-goom_irand(info->gRandom,info->screen.width/3);
  179. radius *= 1.5;
  180. vage = 0.002f;
  181. break;
  182. case FOUNTAIN_FX:
  183. my = info->screen.height+2;
  184. vage = 0.001f;
  185. radius += 1.0f;
  186. mx = info->screen.width / 2;
  187. gravity = 0.04f;
  188. break;
  189. default:
  190. return;
  191. /* my = i R A N D (info->screen.height); vage = 0.01f; */
  192. }
  193. radius *= info->screen.height / 200.0f; /* why 200 ? because the FX was developped on 320x200 */
  194. max *= info->screen.height / 200.0f;
  195. if (info->sound.timeSinceLastBigGoom < 1) {
  196. radius *= 1.5;
  197. max *= 2;
  198. }
  199. for (i=0;i<max;++i)
  200. addABomb (data,mx,my,radius,vage,gravity,info);
  201. }
  202. /**
  203. * Main methode of the FX.
  204. */
  205. static void fs_apply(VisualFX *_this, Pixel *src, Pixel *dest, PluginInfo *info) {
  206. int i;
  207. int col;
  208. FSData *data = (FSData*)_this->fx_data;
  209. /* Get the new parameters values */
  210. data->min_age = 1.0f - (float)IVAL(data->min_age_p)/100.0f;
  211. data->max_age = 1.0f - (float)IVAL(data->max_age_p)/100.0f;
  212. FVAL(data->nbStars_p) = (float)data->nbStars / (float)data->maxStars;
  213. data->nbStars_p.change_listener(&data->nbStars_p);
  214. data->maxStars = IVAL(data->nbStars_limit_p);
  215. data->fx_mode = IVAL(data->fx_mode_p);
  216. /* look for events */
  217. if (info->sound.timeSinceLastGoom < 1) {
  218. fs_sound_event_occured(_this, info);
  219. if (goom_irand(info->gRandom,20)==1) {
  220. IVAL(data->fx_mode_p) = goom_irand(info->gRandom,(LAST_FX*3));
  221. data->fx_mode_p.change_listener(&data->fx_mode_p);
  222. }
  223. }
  224. /* update particules */
  225. for (i=0;i<data->nbStars;++i) {
  226. updateStar(&data->stars[i]);
  227. /* dead particule */
  228. if (data->stars[i].age>=NCOL)
  229. continue;
  230. /* choose the color of the particule */
  231. col = colval[(int)data->stars[i].age];
  232. /* draws the particule */
  233. info->methods.draw_line(dest,(int)data->stars[i].x,(int)data->stars[i].y,
  234. (int)(data->stars[i].x-data->stars[i].vx*6),
  235. (int)(data->stars[i].y-data->stars[i].vy*6),
  236. col,
  237. (int)info->screen.width, (int)info->screen.height);
  238. info->methods.draw_line(dest,(int)data->stars[i].x,(int)data->stars[i].y,
  239. (int)(data->stars[i].x-data->stars[i].vx*2),
  240. (int)(data->stars[i].y-data->stars[i].vy*2),
  241. col,
  242. (int)info->screen.width, (int)info->screen.height);
  243. }
  244. /* look for dead particules */
  245. for (i=0;i<data->nbStars;) {
  246. if ((data->stars[i].x > info->screen.width + 64)
  247. ||((data->stars[i].vy>=0)&&(data->stars[i].y - 16*data->stars[i].vy > info->screen.height))
  248. ||(data->stars[i].x < -64)
  249. ||(data->stars[i].age>=NCOL)) {
  250. data->stars[i] = data->stars[data->nbStars-1];
  251. data->nbStars--;
  252. }
  253. else ++i;
  254. }
  255. }
  256. VisualFX flying_star_create(void) {
  257. VisualFX vfx;
  258. vfx.init = fs_init;
  259. vfx.free = fs_free;
  260. vfx.apply = fs_apply;
  261. vfx.fx_data = 0;
  262. return vfx;
  263. }