1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#ifndef LOVE_GRAPHICS_PARTICLE_SYSTEM_H
22#define LOVE_GRAPHICS_PARTICLE_SYSTEM_H
23
24// LOVE
25#include "common/int.h"
26#include "common/math.h"
27#include "common/Vector.h"
28#include "common/Color.h"
29#include "Drawable.h"
30#include "Quad.h"
31#include "Texture.h"
32#include "Buffer.h"
33
34// STL
35#include <vector>
36
37namespace love
38{
39namespace graphics
40{
41
42class Graphics;
43
44/**
45 * A class for creating, moving and drawing particles.
46 * A big thanks to bobthebloke.org
47 **/
48class ParticleSystem : public Drawable
49{
50public:
51
52 static love::Type type;
53
54 /**
55 * Type of distribution new particles are drawn from: None, uniform, normal, ellipse, borderellipse, borderrectangle.
56 */
57 enum AreaSpreadDistribution
58 {
59 DISTRIBUTION_NONE,
60 DISTRIBUTION_UNIFORM,
61 DISTRIBUTION_NORMAL,
62 DISTRIBUTION_ELLIPSE,
63 DISTRIBUTION_BORDER_ELLIPSE,
64 DISTRIBUTION_BORDER_RECTANGLE,
65 DISTRIBUTION_MAX_ENUM
66 };
67
68 /**
69 * Insertion modes of new particles in the list: top, bottom, random.
70 */
71 enum InsertMode
72 {
73 INSERT_MODE_TOP,
74 INSERT_MODE_BOTTOM,
75 INSERT_MODE_RANDOM,
76 INSERT_MODE_MAX_ENUM
77 };
78
79 /**
80 * Maximum numbers of particles in a ParticleSystem.
81 * This limit comes from the fact that a quad requires four vertices and the
82 * OpenGL API where GLsizei is a signed int.
83 **/
84 static const uint32 MAX_PARTICLES = LOVE_INT32_MAX / 4;
85
86 /**
87 * Creates a particle system with the specified buffer size and texture.
88 **/
89 ParticleSystem(Texture *texture, uint32 buffer);
90 ParticleSystem(const ParticleSystem &p);
91
92 /**
93 * Deletes any allocated memory.
94 **/
95 virtual ~ParticleSystem();
96
97 /**
98 * Creates an identical copy of this ParticleSystem. The clone does not
99 * duplicate any existing particles from this ParticleSystem, just the
100 * settable parameters.
101 **/
102 ParticleSystem *clone();
103
104 /**
105 * Sets the texture used in the particle system.
106 * @param texture The new texture.
107 **/
108 void setTexture(Texture *texture);
109
110 /**
111 * Returns the texture used when drawing the particle system.
112 **/
113 Texture *getTexture() const;
114
115 /**
116 * Clears the current buffer and allocates the appropriate amount of space for the buffer.
117 * @param size The new buffer size.
118 **/
119 void setBufferSize(uint32 size);
120
121 /**
122 * Returns the total amount of particles this ParticleSystem can have active
123 * at any given point in time.
124 **/
125 uint32 getBufferSize() const;
126
127 /**
128 * Sets the insert mode for new particles.
129 * @param mode The new insert mode.
130 */
131 void setInsertMode(InsertMode mode);
132
133 /**
134 * Returns the current insert mode.
135 */
136 InsertMode getInsertMode() const;
137
138 /**
139 * Sets the emission rate.
140 * @param rate The amount of particles per second.
141 **/
142 void setEmissionRate(float rate);
143
144 /**
145 * Returns the number of particles created per second.
146 **/
147 float getEmissionRate() const;
148
149 /**
150 * Sets the lifetime of the particle emitter (-1 means eternal)
151 * @param life The lifetime (in seconds).
152 **/
153 void setEmitterLifetime(float life);
154
155 /**
156 * Returns the lifetime of the particle emitter.
157 **/
158 float getEmitterLifetime() const;
159
160 /**
161 * Sets the life range of the particles.
162 * @param min The minimum life.
163 * @param max The maximum life (if 0, then becomes the same as minimum life).
164 **/
165 void setParticleLifetime(float min, float max = 0);
166
167 /**
168 * Gets the lifetime of a particle.
169 * @param[out] min The minimum life.
170 * @param[out] max The maximum life.
171 **/
172 void getParticleLifetime(float &min, float &max) const;
173
174 /**
175 * Sets the position of the center of the emitter.
176 * Used to move the emitter without changing the position of already existing particles.
177 * @param x The x-coordinate.
178 * @param y The y-coordinate.
179 **/
180 void setPosition(float x, float y);
181
182 /**
183 * Returns the position of the emitter.
184 **/
185 const love::Vector2 &getPosition() const;
186
187 /**
188 * Moves the position of the center of the emitter.
189 * When update is called, newly spawned particles will appear in a line
190 * between the old emitter position and where the emitter was moved to,
191 * resulting in a smoother-feeling particle system if moveTo is called
192 * repeatedly.
193 **/
194 void moveTo(float x, float y);
195
196 /**
197 * Sets the emission area spread parameters and distribution type. The interpretation of
198 * the parameters depends on the distribution type:
199 *
200 * * None: Parameters are ignored. No area spread.
201 * * Uniform: Parameters denote maximal (symmetric) displacement from emitter position.
202 * * Normal: Parameters denote the standard deviation in x and y direction. x and y are assumed to be uncorrelated.
203 * * borderellipse: Parameter causes particle distribution around outside of ellipse
204 * * borderrectangle: Parameter causes particle distribution around outside of rectangle
205 * @param distribution Distribution type
206 * @param x First parameter. Interpretation depends on distribution type.
207 * @param y Second parameter. Interpretation depends on distribution type.
208 * @param angle The angle of the emission area (in radians).
209 * @param directionRelativeToCenter whether the initial direction of
210 * particles points away from the center of the emission area.
211 **/
212 void setEmissionArea(AreaSpreadDistribution distribution, float x, float y, float angle, bool directionRelativeToCenter);
213
214 /**
215 * Returns area spread parameters.
216 **/
217 AreaSpreadDistribution getEmissionArea(love::Vector2 &params, float &angle, bool &directionRelativeToCenter) const;
218
219 /**
220 * Sets the direction of the particle emitter.
221 * @param direction The direction (in degrees).
222 **/
223 void setDirection(float direction);
224
225 /**
226 * Returns the direction of the particle emitter (in radians).
227 **/
228 float getDirection() const;
229
230 /**
231 * Sets the spread of the particle emitter.
232 * @param spread The spread (in radians).
233 **/
234 void setSpread(float spread);
235
236 /**
237 * Returns the directional spread of the emitter (in radians).
238 **/
239 float getSpread() const;
240
241 /**
242 * Sets the speed of the particles.
243 * @param speed The speed.
244 **/
245 void setSpeed(float speed);
246
247 /**
248 * Sets the speed of the particles.
249 * @param min The minimum speed.
250 * @param max The maximum speed.
251 **/
252 void setSpeed(float min, float max);
253
254 /**
255 * Gets the speed of the particles.
256 * @param[out] min The minimum speed.
257 * @param[out] max The maximum speed.
258 **/
259 void getSpeed(float &min, float &max) const;
260
261 /**
262 * Sets the linear acceleration (the acceleration along the x and y axes).
263 * @param x The acceleration along the x-axis.
264 * @param y The acceleration along the y-axis.
265 **/
266 void setLinearAcceleration(float x, float y);
267
268 /**
269 * Sets the linear acceleration (the acceleration along the x and y axes).
270 * @param xmin The minimum amount of acceleration along the x-axis.
271 * @param ymin The minimum amount of acceleration along the y-axis.
272 * @param xmax The maximum amount of acceleration along the x-axis.
273 * @param ymax The maximum amount of acceleration along the y-axis.
274 **/
275 void setLinearAcceleration(float xmin, float ymin, float xmax, float ymax);
276
277 /**
278 * Gets the linear acceleration of the particles.
279 * @param[out] min The minimum acceleration.
280 * @param[out] max The maximum acceleration.
281 **/
282 void getLinearAcceleration(love::Vector2 &min, love::Vector2 &max) const;
283
284 /**
285 * Sets the radial acceleration (the acceleration towards the particle emitter).
286 * @param acceleration The amount of acceleration.
287 **/
288 void setRadialAcceleration(float acceleration);
289
290 /**
291 * Sets the radial acceleration (the acceleration towards the particle emitter).
292 * @param min The minimum acceleration.
293 * @param max The maximum acceleration.
294 **/
295 void setRadialAcceleration(float min, float max);
296
297 /**
298 * Gets the radial acceleration.
299 * @param[out] min The minimum amount of radial acceleration.
300 * @param[out] max The maximum amount of radial acceleration.
301 **/
302 void getRadialAcceleration(float &min, float &max) const;
303
304 /**
305 * Sets the tangential acceleration (the acceleration perpendicular to the particle's direction).
306 * @param acceleration The amount of acceleration.
307 **/
308 void setTangentialAcceleration(float acceleration);
309
310 /**
311 * Sets the tangential acceleration (the acceleration perpendicular to the particle's direction).
312 * @param min The minimum acceleration.
313 * @param max The maximum acceleration.
314 **/
315 void setTangentialAcceleration(float min, float max);
316
317 /**
318 * Gets the tangential acceleration.
319 * @param[out] min The minimum tangential acceleration.
320 * @param[out] max The maximum tangential acceleration.
321 **/
322 void getTangentialAcceleration(float &min, float &max) const;
323
324 /**
325 * Sets the amount of linear damping. Damping reduces the velocity of
326 * particles over time. A value of 0 corresponds to no damping.
327 **/
328 void setLinearDamping(float min, float max);
329
330 /**
331 * Gets the current amount of linear damping.
332 **/
333 void getLinearDamping(float &min, float &max) const;
334
335 /**
336 * Sets the size of the sprite (1.0 being the default size).
337 * @param size The size of the sprite.
338 **/
339 void setSize(float size);
340
341 /**
342 * Sets the sizes of the sprite upon creation and upon death (1.0 being the default size).
343 * @param newSizes Array of sizes
344 **/
345 void setSizes(const std::vector<float> &newSizes);
346
347 /**
348 * Returns the sizes of the particle sprites.
349 **/
350 const std::vector<float> &getSizes() const;
351
352 /**
353 * Sets the amount of variation to the sprite's beginning size (0 being no variation and 1.0 a random size between start and end).
354 * @param variation The amount of variation.
355 **/
356 void setSizeVariation(float variation);
357
358 /**
359 * Returns the amount of initial size variation between particles.
360 **/
361 float getSizeVariation() const;
362
363 /**
364 * Sets the amount of rotation a sprite starts out with.
365 * @param rotation The amount of rotation.
366 **/
367 void setRotation(float rotation);
368
369 /**
370 * Sets the amount of rotation a sprite starts out with (a random value between min and max).
371 * @param min The minimum amount of rotation.
372 * @param max The maximum amount of rotation.
373 **/
374 void setRotation(float min, float max);
375
376 /**
377 * Gets the initial amount of rotation of a particle, in radians.
378 * @param[out] min The minimum initial rotation.
379 * @param[out] max The maximum initial rotation.
380 **/
381 void getRotation(float &min, float &max) const;
382
383 /**
384 * Sets the spin of the sprite.
385 * @param spin The spin of the sprite (in degrees).
386 **/
387 void setSpin(float spin);
388
389 /**
390 * Sets the spin of the sprite upon particle creation and death.
391 * @param start The spin of the sprite upon creation (in radians / second).
392 * @param end The spin of the sprite upon death (in radians / second).
393 **/
394 void setSpin(float start, float end);
395
396 /**
397 * Gets the amount of spin of a particle during its lifetime.
398 * @param[out] start The initial spin, in radians / s.
399 * @param[out] end The final spin, in radians / s.
400 **/
401 void getSpin(float &start, float &end) const;
402
403 /**
404 * Sets the variation of the start spin (0 being no variation and 1 being a random spin between start and end).
405 * @param variation The variation.
406 **/
407 void setSpinVariation(float variation);
408
409 /**
410 * Returns the amount of variation of the start spin of a particle.
411 **/
412 float getSpinVariation() const;
413
414 /**
415 * Sets the particles' offsets for rotation.
416 * @param x The x offset.
417 * @param y The y offset.
418 **/
419 void setOffset(float x, float y);
420
421 /**
422 * Returns of the particle offset.
423 **/
424 love::Vector2 getOffset() const;
425
426 /**
427 * Sets the color of the particles.
428 * @param newColors Array of colors
429 **/
430 void setColor(const std::vector<Colorf> &newColors);
431
432 /**
433 * Returns the color of the particles.
434 **/
435 std::vector<Colorf> getColor() const;
436
437 /**
438 * Sets a list of Quads to use for particles over their lifetime.
439 **/
440 void setQuads(const std::vector<Quad *> &newQuads);
441 void setQuads();
442
443 /**
444 * Gets the Quads used when drawing the particles.
445 **/
446 std::vector<Quad *> getQuads() const;
447
448 /**
449 * sets whether particle angles & rotations are relative to their velocities.
450 **/
451 void setRelativeRotation(bool enable);
452 bool hasRelativeRotation() const;
453
454 /**
455 * Returns the amount of particles that are currently active in the system.
456 **/
457 uint32 getCount() const;
458
459 /**
460 * Starts/resumes the particle emitter.
461 **/
462 void start();
463
464 /**
465 * Stops the particle emitter and resets.
466 **/
467 void stop();
468
469 /**
470 * Pauses the particle emitter.
471 **/
472 void pause();
473
474 /**
475 * Resets the particle emitter.
476 **/
477 void reset();
478
479 /**
480 * Instantly emits a number of particles.
481 * @param num The number of particles to emit.
482 **/
483 void emit(uint32 num);
484
485 /**
486 * Returns whether the particle emitter is active.
487 **/
488 bool isActive() const;
489
490 /**
491 * Returns whether the particle emitter is paused.
492 **/
493 bool isPaused() const;
494
495 bool isStopped() const;
496
497 /**
498 * Returns whether the particle system is empty of particles or not.
499 **/
500 bool isEmpty() const;
501
502 /**
503 * Returns whether the amount of particles has reached the buffer limit or not.
504 **/
505 bool isFull() const;
506
507 /**
508 * Updates the particle system.
509 * @param dt Time since last update.
510 **/
511 void update(float dt);
512
513 // Implements Drawable.
514 void draw(Graphics *gfx, const Matrix4 &m) override;
515
516 static bool getConstant(const char *in, AreaSpreadDistribution &out);
517 static bool getConstant(AreaSpreadDistribution in, const char *&out);
518 static std::vector<std::string> getConstants(AreaSpreadDistribution);
519
520 static bool getConstant(const char *in, InsertMode &out);
521 static bool getConstant(InsertMode in, const char *&out);
522 static std::vector<std::string> getConstants(InsertMode);
523
524private:
525
526 // Represents a single particle.
527 struct Particle
528 {
529 Particle *prev;
530 Particle *next;
531
532 float lifetime;
533 float life;
534
535 love::Vector2 position;
536
537 // Particles gravitate towards this point.
538 love::Vector2 origin;
539
540 love::Vector2 velocity;
541 love::Vector2 linearAcceleration;
542 float radialAcceleration;
543 float tangentialAcceleration;
544
545 float linearDamping;
546
547 float size;
548 float sizeOffset;
549 float sizeIntervalSize;
550
551 float rotation; // Amount of rotation applied to the final angle.
552 float angle;
553 float spinStart;
554 float spinEnd;
555
556 Colorf color;
557
558 int quadIndex;
559 };
560
561 void resetOffset();
562
563 void createBuffers(size_t size);
564 void deleteBuffers();
565
566 void addParticle(float t);
567 Particle *removeParticle(Particle *p);
568
569 // Called by addParticle.
570 void initParticle(Particle *p, float t);
571 void insertTop(Particle *p);
572 void insertBottom(Particle *p);
573 void insertRandom(Particle *p);
574
575 // Pointer to the beginning of the allocated memory.
576 Particle *pMem;
577
578 // Pointer to a free particle.
579 Particle *pFree;
580
581 // Pointer to the start of the linked list.
582 Particle *pHead;
583
584 // Pointer to the end of the linked list.
585 Particle *pTail;
586
587 // The texture to be drawn.
588 StrongRef<Texture> texture;
589
590 // Whether the particle emitter is active.
591 bool active;
592
593 // Insert mode of new particles.
594 InsertMode insertMode;
595
596 // The maximum number of particles.
597 uint32 maxParticles;
598
599 // The number of active particles.
600 uint32 activeParticles;
601
602 // The emission rate (particles/sec).
603 float emissionRate;
604
605 // Used to determine when a particle should be emitted.
606 float emitCounter;
607
608 // The relative position of the particle emitter.
609 love::Vector2 position;
610 love::Vector2 prevPosition;
611
612 // Emission area spread.
613 AreaSpreadDistribution emissionAreaDistribution;
614 love::Vector2 emissionArea;
615 float emissionAreaAngle;
616 bool directionRelativeToEmissionCenter;
617
618 // The lifetime of the particle emitter (-1 means infinite) and the life it has left.
619 float lifetime;
620 float life;
621
622 // The particle life.
623 float particleLifeMin;
624 float particleLifeMax;
625
626 // The direction (and spread) the particles will be emitted in. Measured in radians.
627 float direction;
628 float spread;
629
630 // The speed.
631 float speedMin;
632 float speedMax;
633
634 // Acceleration along the x and y axes.
635 love::Vector2 linearAccelerationMin;
636 love::Vector2 linearAccelerationMax;
637
638 // Acceleration towards the emitter's center
639 float radialAccelerationMin;
640 float radialAccelerationMax;
641
642 // Acceleration perpendicular to the particle's direction.
643 float tangentialAccelerationMin;
644 float tangentialAccelerationMax;
645
646 float linearDampingMin;
647 float linearDampingMax;
648
649 // Size.
650 std::vector<float> sizes;
651 float sizeVariation;
652
653 // Rotation
654 float rotationMin;
655 float rotationMax;
656
657 // Spin.
658 float spinStart;
659 float spinEnd;
660 float spinVariation;
661
662 // Offsets
663 love::Vector2 offset;
664
665 // Is the ParticleSystem using a default offset?
666 bool defaultOffset;
667
668 // Color.
669 std::vector<Colorf> colors;
670
671 // Quads.
672 std::vector<StrongRef<Quad>> quads;
673
674 bool relativeRotation;
675
676 const vertex::Attributes vertexAttributes;
677 Buffer *buffer;
678
679 static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
680 static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions;
681
682 static StringMap<InsertMode, INSERT_MODE_MAX_ENUM>::Entry insertModesEntries[];
683 static StringMap<InsertMode, INSERT_MODE_MAX_ENUM> insertModes;
684};
685
686} // graphics
687} // love
688
689#endif // LOVE_GRAPHICS_PARTICLE_SYSTEM_H
690