ParticleEngine.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. using Client.MirGraphics.Particles;
  2. using Client.MirScenes;
  3. using SlimDX;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. namespace Client.MirGraphics
  11. {
  12. public enum ParticleType
  13. {
  14. None = 0,
  15. Fog,
  16. RedFog,
  17. RedFogEmber,
  18. BlueFog,
  19. YellowFog,
  20. WhiteEmber,
  21. YellowEmber,
  22. Test,
  23. Blizzard,
  24. BlizzardFrost,
  25. Bird,
  26. FogCloud,
  27. FloatingFlower,
  28. Sand,
  29. Snow,
  30. FlowersRain,
  31. Rain,
  32. Leaves,
  33. FireyLeaves,
  34. PurpleLeaves
  35. }
  36. public class ParticleEngine
  37. {
  38. public Vector2 EmitterLocation { get; set; }
  39. protected List<Particle> particles;
  40. protected List<ParticleImageInfo> Textures;
  41. public Vector2 ForceVelocity = Vector2.Zero;
  42. public bool GenerateParticles;
  43. public DateTime NextParticleTime;
  44. public DateTime NextVelocityTime;
  45. public TimeSpan NextVelocityUpdate = TimeSpan.FromMilliseconds(500);
  46. public TimeSpan UpdateDelay = TimeSpan.FromMilliseconds(50);
  47. ParticleType type;
  48. public ParticleEngine(List<ParticleImageInfo> textures, Vector2 location, ParticleType type)
  49. {
  50. EmitterLocation = location;
  51. Textures = textures;
  52. particles = new List<Particle>();
  53. GenerateParticles = true;
  54. this.type = type;
  55. }
  56. public virtual Particle GenerateNewParticle(ParticleType type)
  57. {
  58. // Defensive: ensure we have at least one texture to use
  59. if (Textures == null || Textures.Count <= 0)
  60. return null;
  61. // Pick one texture safely once per particle
  62. int count = Textures.Count;
  63. int idx = CMain.Random.Next(count);
  64. if (idx < 0 || idx >= count) idx = count - 1;
  65. var tex = Textures[idx];
  66. Particle particle = null;
  67. switch (type)
  68. {
  69. #region Fog
  70. case ParticleType.Fog:
  71. particle = new FogParticle(this, tex)
  72. {
  73. Color = Color.White,
  74. Size = 1F,
  75. BlendRate = 0.4F,
  76. AliveTime = DateTime.MaxValue,
  77. Blend = false,
  78. //BlendRate = (rate / (float)100),
  79. };
  80. particles.Add(particle);
  81. break;
  82. #endregion
  83. #region Sand
  84. case ParticleType.Sand:
  85. particle = new SandParticle(this, tex)
  86. {
  87. Color = Color.Yellow,
  88. Size = 1F,
  89. BlendRate = 0.2F,
  90. AliveTime = DateTime.MaxValue,
  91. Blend = false,
  92. //BlendRate = (rate / (float)100),
  93. };
  94. particles.Add(particle);
  95. break;
  96. #endregion
  97. #region Snow
  98. case ParticleType.Snow:
  99. particle = new SnowParticle(this, tex)
  100. {
  101. Color = Color.White,
  102. Size = 1F,
  103. BlendRate = 1F,
  104. AliveTime = DateTime.MaxValue,
  105. Blend = true,
  106. //BlendRate = (rate / (float)100),
  107. };
  108. particles.Add(particle);
  109. break;
  110. #endregion
  111. #region Firey Leaves
  112. case ParticleType.FireyLeaves:
  113. particle = new FogParticle(this, tex)
  114. {
  115. Color = Color.Firebrick,
  116. BlendRate = 1F,
  117. AliveTime = DateTime.MaxValue,
  118. Blend = true,
  119. //BlendRate = (rate / (float)100),
  120. };
  121. particles.Add(particle);
  122. break;
  123. #endregion
  124. #region Leaves
  125. case ParticleType.Leaves:
  126. particle = new FogParticle(this, tex)
  127. {
  128. Color = Color.Goldenrod,
  129. BlendRate = 0.1F,
  130. AliveTime = DateTime.MaxValue,
  131. Blend = true,
  132. BlendMode = BlendMode.NORMAL
  133. //BlendRate = (rate / (float)100),
  134. };
  135. particles.Add(particle);
  136. break;
  137. #endregion
  138. #region Purple Leaves
  139. case ParticleType.PurpleLeaves:
  140. particle = new FogParticle(this, tex)
  141. {
  142. Color = Color.Purple,
  143. BlendRate = 0.1F,
  144. AliveTime = DateTime.MaxValue,
  145. Blend = true,
  146. BlendMode = BlendMode.NORMAL
  147. //BlendRate = (rate / (float)100),
  148. };
  149. particles.Add(particle);
  150. break;
  151. #endregion
  152. #region Rain
  153. case ParticleType.Rain:
  154. particle = new Particle()
  155. {
  156. Engine = this,
  157. ImageInfo = tex,
  158. Color = System.Drawing.ColorTranslator.FromHtml("#ffffff85"),
  159. // Color = Color.White,
  160. Size = 1F,
  161. BlendRate = 1F,
  162. AliveTime = DateTime.MaxValue,
  163. Blend = true,
  164. //BlendRate = (rate / (float)100),
  165. };
  166. particles.Add(particle);
  167. break;
  168. #endregion
  169. #region FlowersRain
  170. case ParticleType.FlowersRain:
  171. particle = new FlowerParticle(this, tex)
  172. {
  173. Color = Color.White,
  174. Size = 1F,
  175. BlendRate = 0.5F,
  176. AliveTime = DateTime.MaxValue,
  177. Blend = false,
  178. //BlendRate = (rate / (float)100),
  179. };
  180. particles.Add(particle);
  181. break;
  182. #endregion
  183. #region Yellow Fog
  184. case ParticleType.YellowFog:
  185. particle = new FogParticle(this, tex)
  186. {
  187. Color = Color.Yellow,
  188. Size = 1F,
  189. BlendRate = 0.25F,
  190. AliveTime = DateTime.MaxValue,
  191. Blend = false,
  192. //BlendRate = (rate / (float)100),
  193. };
  194. particles.Add(particle);
  195. break;
  196. #endregion
  197. #region Fog Cloud
  198. case ParticleType.FogCloud:
  199. particle = new FogParticle(this, tex)
  200. {
  201. Color = Color.Transparent,
  202. Size = 1F,
  203. BlendRate = 0.2F,
  204. AliveTime = DateTime.MaxValue,
  205. Blend = false,
  206. //BlendRate = (rate / (float)100),
  207. };
  208. particles.Add(particle);
  209. break;
  210. #endregion
  211. #region RedFog
  212. case ParticleType.RedFog:
  213. particle = new FogParticle(this, tex)
  214. {
  215. Color = Color.DarkRed,
  216. Size = 1F,
  217. AliveTime = DateTime.MaxValue,
  218. BlendRate = 0.2F,
  219. Blend = false,
  220. };
  221. particles.Add(particle);
  222. break;
  223. #endregion
  224. #region FloatingFlower
  225. case ParticleType.FloatingFlower:
  226. particle = new Particle()
  227. {
  228. Engine = this,
  229. ImageInfo = tex,
  230. Color = Color.White,
  231. Size = (float)CMain.Random.NextDouble(),
  232. AliveTime = CMain.Now.AddSeconds(5 + CMain.Random.Next(4)),
  233. Blend = true,
  234. BlendRate = 1F,
  235. Position = new Vector2(CMain.Random.Next(Settings.ScreenWidth), CMain.Random.Next(Settings.ScreenHeight / 4, Settings.ScreenHeight * 2)),
  236. Velocity = new Vector2(-2F * CMain.Random.Next(4), -2F * CMain.Random.Next(3)),
  237. };
  238. particles.Add(particle);
  239. break;
  240. #endregion
  241. #region BlueFog
  242. case ParticleType.BlueFog:
  243. particle = new FogParticle(this, tex)
  244. {
  245. Color = Color.DeepSkyBlue,
  246. Size = 1F,
  247. AliveTime = DateTime.MaxValue,
  248. BlendRate = 0.2F,
  249. Blend = false,
  250. };
  251. particles.Add(particle);
  252. break;
  253. #endregion
  254. #region Blizzard
  255. case ParticleType.Blizzard:
  256. particle = new FogParticle(this, tex)
  257. {
  258. Color = Color.FromArgb(255, 172, 229, 238),
  259. Size = 1F,
  260. AliveTime = DateTime.MaxValue,
  261. BlendRate = 0.2F,
  262. };
  263. particles.Add(particle);
  264. break;
  265. #endregion
  266. #region Blizzard Frost
  267. case ParticleType.BlizzardFrost:
  268. particle = new Particle()
  269. {
  270. Engine = this,
  271. ImageInfo = tex,
  272. Color = Color.White,
  273. Size = (float)CMain.Random.NextDouble(),
  274. AliveTime = CMain.Now.AddSeconds(1 + CMain.Random.Next(2)),
  275. Blend = false,
  276. BlendRate = 0.35F,
  277. Position = new Vector2(CMain.Random.Next(Settings.ScreenWidth), CMain.Random.Next(Settings.ScreenHeight / 2, Settings.ScreenHeight)),
  278. Velocity = new Vector2(0, 3F * CMain.Random.Next(3)),
  279. };
  280. particles.Add(particle);
  281. break;
  282. #endregion
  283. #region Red Fog Ember
  284. case ParticleType.RedFogEmber:
  285. particle = new Particle()
  286. {
  287. Engine = this,
  288. ImageInfo = tex,
  289. Color = Color.DarkRed,
  290. Size = (float)CMain.Random.NextDouble(),
  291. AliveTime = CMain.Now.AddSeconds(1 + CMain.Random.Next(2)),
  292. Blend = true,
  293. BlendRate = 0.35F,
  294. Position = new Vector2(CMain.Random.Next(Settings.ScreenWidth), CMain.Random.Next(Settings.ScreenHeight / 2, Settings.ScreenHeight)),
  295. Velocity = new Vector2(0, -2F * CMain.Random.Next(3)),
  296. };
  297. particles.Add(particle);
  298. break;
  299. #endregion
  300. #region White Ember
  301. case ParticleType.WhiteEmber:
  302. particle = new Particle()
  303. {
  304. Engine = this,
  305. ImageInfo = tex,
  306. Color = Color.White,
  307. Size = (float)CMain.Random.NextDouble(),
  308. AliveTime = CMain.Now.AddSeconds(1 + CMain.Random.Next(2)),
  309. Blend = true,
  310. BlendRate = 0.35F,
  311. Position = new Vector2(CMain.Random.Next(Settings.ScreenWidth), CMain.Random.Next(Settings.ScreenHeight / 2, Settings.ScreenHeight)),
  312. Velocity = new Vector2(0, -2F * CMain.Random.Next(3)),
  313. };
  314. particles.Add(particle);
  315. break;
  316. #endregion
  317. #region Yellow Ember
  318. case ParticleType.YellowEmber:
  319. particle = new Particle()
  320. {
  321. Engine = this,
  322. ImageInfo = tex,
  323. Color = Color.Yellow,
  324. Size = (float)CMain.Random.NextDouble(),
  325. AliveTime = CMain.Now.AddSeconds(1 + CMain.Random.Next(2)),
  326. Blend = true,
  327. BlendRate = 0.35F,
  328. Position = new Vector2(CMain.Random.Next(Settings.ScreenWidth), CMain.Random.Next(Settings.ScreenHeight / 2, Settings.ScreenHeight)),
  329. Velocity = new Vector2(0, -2F * CMain.Random.Next(3)),
  330. };
  331. particles.Add(particle);
  332. break;
  333. #endregion
  334. #region Bird
  335. case ParticleType.Bird:
  336. particle = new Particle()
  337. {
  338. Engine = this,
  339. ImageInfo = tex,
  340. Color = Color.White,
  341. Size = (float)CMain.Random.NextDouble(),
  342. AliveTime = CMain.Now.AddSeconds(1 + CMain.Random.Next(2)),
  343. Blend = true,
  344. BlendRate = 0.35F,
  345. Position = new Vector2(CMain.Random.Next(Settings.ScreenWidth), CMain.Random.Next(Settings.ScreenHeight / 4, Settings.ScreenHeight * 2)),
  346. Velocity = new Vector2(-2, -2F * CMain.Random.Next(3)),
  347. };
  348. particles.Add(particle);
  349. break;
  350. #endregion
  351. }
  352. return particle;
  353. }
  354. protected Particle FindParticleFromLocation(Vector2 positon)
  355. {
  356. foreach (Particle particle in particles)
  357. {
  358. if (particle.Position == positon)
  359. return particle;
  360. }
  361. return null;
  362. }
  363. public virtual void Update()
  364. {
  365. }
  366. public void Process()
  367. {
  368. foreach (var particle in particles)
  369. {
  370. particle.ProcessImage();
  371. }
  372. if (GenerateParticles && CMain.Now > NextParticleTime)
  373. {
  374. NextParticleTime = CMain.Now + UpdateDelay;
  375. GenerateNewParticle(type);
  376. }
  377. for (int particle = 0; particle < particles.Count; particle++)
  378. {
  379. particles[particle].Update();
  380. //particles[particle].ProcessImage();
  381. if (CMain.Now > particles[particle].AliveTime)
  382. {
  383. particles[particle].OnParticleEnd();
  384. particles.RemoveAt(particle);
  385. particle--;
  386. }
  387. }
  388. }
  389. public virtual void Draw()
  390. {
  391. for (int index = 0; index < particles.Count; index++)
  392. particles[index].Draw();
  393. }
  394. public void ParticlesOffSet(Point offset)
  395. {
  396. for (int particle = 0; particle < particles.Count; particle++)
  397. {
  398. var particleObj = particles[particle];
  399. if (particleObj.GetType() == typeof(FogParticle))
  400. continue;
  401. particles[particle].Position += new Vector2(offset.X, offset.Y);
  402. }
  403. }
  404. public void ParticlesOffSet(int x, int y)
  405. {
  406. for (int particle = 0; particle < particles.Count; particle++)
  407. particles[particle].Position += new Vector2(x, y);
  408. }
  409. public void Dispose()
  410. {
  411. for (int i = particles.Count - 1; i >= 0; i--)
  412. {
  413. particles[i].ImageInfo.Library = null;
  414. particles[i].ImageInfo = null;
  415. particles[i].Engine = null;
  416. particles.RemoveAt(i);
  417. }
  418. particles = null;
  419. for (int i = Textures.Count - 1; i >= 0; i--)
  420. {
  421. Textures[i].Library = null;
  422. Textures.RemoveAt(i);
  423. }
  424. Textures = null;
  425. EmitterLocation = Vector2.Zero;
  426. ForceVelocity = Vector2.Zero;
  427. }
  428. }
  429. }