custom_particle_system.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. // SuperTux
  2. // Copyright (C) 2020 A. Semphris <semphris@protonmail.com>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #ifndef HEADER_SUPERTUX_OBJECT_CUSTOM_PARTICLE_SYSTEM_HPP
  17. #define HEADER_SUPERTUX_OBJECT_CUSTOM_PARTICLE_SYSTEM_HPP
  18. #include "math/easing.hpp"
  19. #include "math/vector.hpp"
  20. #include "object/particlesystem_interactive.hpp"
  21. #include "object/particle_zone.hpp"
  22. #include "scripting/custom_particles.hpp"
  23. #include "video/surface.hpp"
  24. #include "video/surface_ptr.hpp"
  25. class CustomParticleSystem :
  26. public ParticleSystem_Interactive,
  27. public ExposedObject<CustomParticleSystem, scripting::CustomParticles>
  28. {
  29. friend class ParticleEditor;
  30. friend class scripting::CustomParticles;
  31. public:
  32. CustomParticleSystem();
  33. CustomParticleSystem(const ReaderMapping& reader);
  34. ~CustomParticleSystem() override;
  35. virtual void draw(DrawingContext& context) override;
  36. void reinit_textures();
  37. virtual void update(float dt_sec) override;
  38. static std::string class_name() { return "particles-custom"; }
  39. virtual std::string get_class_name() const override { return class_name(); }
  40. static std::string display_name() { return _("Custom Particles"); }
  41. virtual std::string get_display_name() const override { return display_name(); }
  42. virtual void save(Writer& writer) override;
  43. virtual ObjectSettings get_settings() override;
  44. virtual const std::string get_icon_path() const override {
  45. return "images/engine/editor/particle.png";
  46. }
  47. virtual void expose(HSQUIRRELVM vm, SQInteger table_idx) override {
  48. ExposedObject<CustomParticleSystem, scripting::CustomParticles>::expose(vm, table_idx);
  49. }
  50. virtual void unexpose(HSQUIRRELVM vm, SQInteger table_idx) override {
  51. ExposedObject<CustomParticleSystem, scripting::CustomParticles>::unexpose(vm, table_idx);
  52. }
  53. //void fade_amount(int new_amount, float fade_time);
  54. protected:
  55. virtual int collision(Particle* particle, const Vector& movement) override;
  56. CollisionHit get_collision(Particle* particle, const Vector& movement);
  57. private:
  58. struct ease_request
  59. {
  60. float* value;
  61. float begin;
  62. float end;
  63. float time_total;
  64. float time_remain;
  65. easing func;
  66. };
  67. // Local
  68. void add_particle(float lifetime, float x, float y);
  69. void spawn_particles(float lifetime);
  70. std::vector<ParticleZone::ZoneDetails> get_zones();
  71. float get_abs_x();
  72. float get_abs_y();
  73. float texture_sum_odds;
  74. float time_last_remaining;
  75. public:
  76. // Scripting
  77. void clear() { custom_particles.clear(); }
  78. void ease_value(float* value, float target, float time, easing func);
  79. private:
  80. std::vector<ease_request> script_easings;
  81. enum class RotationMode {
  82. Fixed,
  83. Facing,
  84. Wiggling
  85. };
  86. enum class FadeMode {
  87. None,
  88. Fade,
  89. Shrink
  90. };
  91. enum class CollisionMode {
  92. Ignore,
  93. Stick,
  94. StickForever,
  95. BounceHeavy,
  96. BounceLight,
  97. Destroy,
  98. FadeOut
  99. };
  100. enum class OffscreenMode {
  101. Never,
  102. OnlyOnExit,
  103. Always
  104. };
  105. class SpriteProperties final
  106. {
  107. public:
  108. float likeliness;
  109. Color color;
  110. SurfacePtr texture;
  111. Vector scale;
  112. Vector hb_scale;
  113. Vector hb_offset;
  114. SpriteProperties() :
  115. likeliness(1.f),
  116. color(1.f, 1.f, 1.f, 1.f),
  117. texture(Surface::from_file("images/engine/editor/particle.png")),
  118. scale(1.f, 1.f),
  119. hb_scale(1.f, 1.f),
  120. hb_offset(0.f, 0.f)
  121. {
  122. }
  123. SpriteProperties(const SurfacePtr& surface) :
  124. likeliness(1.f),
  125. color(1.f, 1.f, 1.f, 1.f),
  126. texture(surface),
  127. scale(1.f, 1.f),
  128. hb_scale(1.f, 1.f),
  129. hb_offset(0.f, 0.f)
  130. {
  131. }
  132. SpriteProperties(const SpriteProperties& sp, float alpha) :
  133. likeliness(sp.likeliness),
  134. color(sp.color.red, sp.color.green, sp.color.blue, sp.color.alpha * alpha),
  135. texture(sp.texture),
  136. scale(sp.scale),
  137. hb_scale(sp.hb_scale),
  138. hb_offset(sp.hb_offset)
  139. {
  140. }
  141. inline bool operator==(const SpriteProperties& sp)
  142. {
  143. return this->likeliness == sp.likeliness
  144. && this->color == sp.color
  145. && this->texture == sp.texture
  146. && this->scale == sp.scale
  147. && this->hb_scale == sp.hb_scale
  148. && this->hb_offset == sp.hb_offset;
  149. }
  150. inline bool operator!=(const SpriteProperties& sp)
  151. {
  152. return !operator==(sp);
  153. }
  154. };
  155. SpriteProperties get_random_texture();
  156. class CustomParticle : public Particle
  157. {
  158. public:
  159. SpriteProperties original_props, props;
  160. float lifetime, birth_time, death_time,
  161. total_birth, total_death;
  162. FadeMode birth_mode, death_mode;
  163. EasingMode birth_easing, death_easing;
  164. bool ready_for_deletion;
  165. float speedX, speedY,
  166. accX, accY,
  167. frictionX, frictionY;
  168. float feather_factor;
  169. float angle_speed, angle_acc,
  170. angle_decc;
  171. RotationMode angle_mode;
  172. CollisionMode collision_mode;
  173. OffscreenMode offscreen_mode;
  174. bool has_been_on_screen;
  175. bool has_been_in_life_zone;
  176. bool last_life_zone_required_instakill;
  177. bool stuck;
  178. CustomParticle() :
  179. original_props(),
  180. props(),
  181. lifetime(),
  182. birth_time(),
  183. death_time(),
  184. total_birth(),
  185. total_death(),
  186. birth_mode(),
  187. death_mode(),
  188. birth_easing(),
  189. death_easing(),
  190. ready_for_deletion(false),
  191. speedX(),
  192. speedY(),
  193. accX(),
  194. accY(),
  195. frictionX(),
  196. frictionY(),
  197. feather_factor(),
  198. angle_speed(),
  199. angle_acc(),
  200. angle_decc(),
  201. angle_mode(),
  202. collision_mode(),
  203. offscreen_mode(),
  204. has_been_on_screen(),
  205. has_been_in_life_zone(false),
  206. last_life_zone_required_instakill(false),
  207. stuck(false)
  208. {}
  209. };
  210. std::vector<SpriteProperties> m_textures;
  211. std::vector<std::unique_ptr<CustomParticle> > custom_particles;
  212. std::string m_particle_main_texture;
  213. int m_max_amount;
  214. float m_delay;
  215. float m_particle_lifetime;
  216. float m_particle_lifetime_variation;
  217. float m_particle_birth_time,
  218. m_particle_birth_time_variation,
  219. m_particle_death_time,
  220. m_particle_death_time_variation;
  221. FadeMode m_particle_birth_mode,
  222. m_particle_death_mode;
  223. EasingMode m_particle_birth_easing,
  224. m_particle_death_easing;
  225. float m_particle_speed_x,
  226. m_particle_speed_y,
  227. m_particle_speed_variation_x,
  228. m_particle_speed_variation_y,
  229. m_particle_acceleration_x,
  230. m_particle_acceleration_y,
  231. m_particle_friction_x,
  232. m_particle_friction_y;
  233. float m_particle_feather_factor;
  234. float m_particle_rotation,
  235. m_particle_rotation_variation,
  236. m_particle_rotation_speed,
  237. m_particle_rotation_speed_variation,
  238. m_particle_rotation_acceleration,
  239. m_particle_rotation_decceleration;
  240. RotationMode m_particle_rotation_mode;
  241. CollisionMode m_particle_collision_mode;
  242. OffscreenMode m_particle_offscreen_mode;
  243. bool m_cover_screen;
  244. public:
  245. // TODO: Put all those member variables in some (abstract?) class of which
  246. // both CustomParticlesSystem and ParticleProbs will inherit (so that
  247. // I don't have to write all the variables 4 times just in the header)
  248. // For the particle editor
  249. class ParticleProps final
  250. {
  251. public:
  252. std::vector<SpriteProperties> m_textures;
  253. std::string m_particle_main_texture;
  254. int m_max_amount;
  255. float m_delay;
  256. float m_particle_lifetime;
  257. float m_particle_lifetime_variation;
  258. float m_particle_birth_time,
  259. m_particle_birth_time_variation,
  260. m_particle_death_time,
  261. m_particle_death_time_variation;
  262. FadeMode m_particle_birth_mode,
  263. m_particle_death_mode;
  264. EasingMode m_particle_birth_easing,
  265. m_particle_death_easing;
  266. float m_particle_speed_x,
  267. m_particle_speed_y,
  268. m_particle_speed_variation_x,
  269. m_particle_speed_variation_y,
  270. m_particle_acceleration_x,
  271. m_particle_acceleration_y,
  272. m_particle_friction_x,
  273. m_particle_friction_y;
  274. float m_particle_feather_factor;
  275. float m_particle_rotation,
  276. m_particle_rotation_variation,
  277. m_particle_rotation_speed,
  278. m_particle_rotation_speed_variation,
  279. m_particle_rotation_acceleration,
  280. m_particle_rotation_decceleration;
  281. RotationMode m_particle_rotation_mode;
  282. CollisionMode m_particle_collision_mode;
  283. OffscreenMode m_particle_offscreen_mode;
  284. bool m_cover_screen;
  285. ParticleProps() :
  286. m_textures(),
  287. m_particle_main_texture(),
  288. m_max_amount(25),
  289. m_delay(0.1f),
  290. m_particle_lifetime(5.f),
  291. m_particle_lifetime_variation(0.f),
  292. m_particle_birth_time(0.f),
  293. m_particle_birth_time_variation(0.f),
  294. m_particle_death_time(0.f),
  295. m_particle_death_time_variation(0.f),
  296. m_particle_birth_mode(),
  297. m_particle_death_mode(),
  298. m_particle_birth_easing(),
  299. m_particle_death_easing(),
  300. m_particle_speed_x(0.f),
  301. m_particle_speed_y(0.f),
  302. m_particle_speed_variation_x(0.f),
  303. m_particle_speed_variation_y(0.f),
  304. m_particle_acceleration_x(0.f),
  305. m_particle_acceleration_y(0.f),
  306. m_particle_friction_x(0.f),
  307. m_particle_friction_y(0.f),
  308. m_particle_feather_factor(0.f),
  309. m_particle_rotation(0.f),
  310. m_particle_rotation_variation(0.f),
  311. m_particle_rotation_speed(0.f),
  312. m_particle_rotation_speed_variation(0.f),
  313. m_particle_rotation_acceleration(0.f),
  314. m_particle_rotation_decceleration(0.f),
  315. m_particle_rotation_mode(),
  316. m_particle_collision_mode(),
  317. m_particle_offscreen_mode(),
  318. m_cover_screen(true)
  319. {
  320. }
  321. };
  322. std::unique_ptr<ParticleProps> get_props() const
  323. {
  324. std::unique_ptr<ParticleProps> props = std::make_unique<ParticleProps>();
  325. for (auto& texture : m_textures)
  326. props->m_textures.push_back(texture);
  327. props->m_particle_main_texture = m_particle_main_texture;
  328. props->m_max_amount = m_max_amount;
  329. props->m_delay = m_delay;
  330. props->m_particle_lifetime = m_particle_lifetime;
  331. props->m_particle_lifetime_variation = m_particle_lifetime_variation;
  332. props->m_particle_birth_time = m_particle_birth_time;
  333. props->m_particle_birth_time_variation = m_particle_birth_time_variation;
  334. props->m_particle_death_time = m_particle_death_time;
  335. props->m_particle_death_time_variation = m_particle_death_time_variation;
  336. props->m_particle_birth_mode = m_particle_birth_mode;
  337. props->m_particle_death_mode = m_particle_death_mode;
  338. props->m_particle_birth_easing = m_particle_birth_easing;
  339. props->m_particle_death_easing = m_particle_death_easing;
  340. props->m_particle_speed_x = m_particle_speed_x;
  341. props->m_particle_speed_y = m_particle_speed_y;
  342. props->m_particle_speed_variation_x = m_particle_speed_variation_x;
  343. props->m_particle_speed_variation_y = m_particle_speed_variation_y;
  344. props->m_particle_acceleration_x = m_particle_acceleration_x;
  345. props->m_particle_acceleration_y = m_particle_acceleration_y;
  346. props->m_particle_friction_x = m_particle_friction_x;
  347. props->m_particle_friction_y = m_particle_friction_y;
  348. props->m_particle_feather_factor = m_particle_feather_factor;
  349. props->m_particle_rotation = m_particle_rotation;
  350. props->m_particle_rotation_variation = m_particle_rotation_variation;
  351. props->m_particle_rotation_speed = m_particle_rotation_speed;
  352. props->m_particle_rotation_speed_variation = m_particle_rotation_speed_variation;
  353. props->m_particle_rotation_acceleration = m_particle_rotation_acceleration;
  354. props->m_particle_rotation_decceleration = m_particle_rotation_decceleration;
  355. props->m_particle_rotation_mode = m_particle_rotation_mode;
  356. props->m_particle_collision_mode = m_particle_collision_mode;
  357. props->m_particle_offscreen_mode = m_particle_offscreen_mode;
  358. props->m_cover_screen = m_cover_screen;
  359. return props;
  360. }
  361. void set_props(ParticleProps* props)
  362. {
  363. m_textures.clear();
  364. for (auto& texture : props->m_textures)
  365. m_textures.push_back(texture);
  366. m_particle_main_texture = props->m_particle_main_texture;
  367. m_max_amount = props->m_max_amount;
  368. m_delay = props->m_delay;
  369. m_particle_lifetime = props->m_particle_lifetime;
  370. m_particle_lifetime_variation = props->m_particle_lifetime_variation;
  371. m_particle_birth_time = props->m_particle_birth_time;
  372. m_particle_birth_time_variation = props->m_particle_birth_time_variation;
  373. m_particle_death_time = props->m_particle_death_time;
  374. m_particle_death_time_variation = props->m_particle_death_time_variation;
  375. m_particle_birth_mode = props->m_particle_birth_mode;
  376. m_particle_death_mode = props->m_particle_death_mode;
  377. m_particle_birth_easing = props->m_particle_birth_easing;
  378. m_particle_death_easing = props->m_particle_death_easing;
  379. m_particle_speed_x = props->m_particle_speed_x;
  380. m_particle_speed_y = props->m_particle_speed_y;
  381. m_particle_speed_variation_x = props->m_particle_speed_variation_x;
  382. m_particle_speed_variation_y = props->m_particle_speed_variation_y;
  383. m_particle_acceleration_x = props->m_particle_acceleration_x;
  384. m_particle_acceleration_y = props->m_particle_acceleration_y;
  385. m_particle_friction_x = props->m_particle_friction_x;
  386. m_particle_friction_y = props->m_particle_friction_y;
  387. m_particle_feather_factor = props->m_particle_feather_factor;
  388. m_particle_rotation = props->m_particle_rotation;
  389. m_particle_rotation_variation = props->m_particle_rotation_variation;
  390. m_particle_rotation_speed = props->m_particle_rotation_speed;
  391. m_particle_rotation_speed_variation = props->m_particle_rotation_speed_variation;
  392. m_particle_rotation_acceleration = props->m_particle_rotation_acceleration;
  393. m_particle_rotation_decceleration = props->m_particle_rotation_decceleration;
  394. m_particle_rotation_mode = props->m_particle_rotation_mode;
  395. m_particle_collision_mode = props->m_particle_collision_mode;
  396. m_particle_offscreen_mode = props->m_particle_offscreen_mode;
  397. m_cover_screen = props->m_cover_screen;
  398. }
  399. private:
  400. CustomParticleSystem(const CustomParticleSystem&) = delete;
  401. CustomParticleSystem& operator=(const CustomParticleSystem&) = delete;
  402. };
  403. #endif
  404. /* EOF */